在解析文章中的代码时,我一直觉得自己根本无法达到如此高的水平。不幸的是,由于我的无能,我无法理解它。
我请作者举例说明(现成的代码),如何将这一功能添加到所介绍的工具包中?
fxsaber, 2020.01.14 11:42 AM
uchar Bytes2[]; if (MTTESTER::GetLastTstCache(Bytes2) != -1) // 如果可以读取单次运行的最后一条缓存记录 { const SINGLETESTERCACHE SingleTesterCache(Bytes2); // 将其驱动到相应的对象中。
fxsaber, 2019.11.11 04:45 PM.
uchar Bytes[]; MTTESTER::GetLastOptCache(Bytes); // TESTERCACHE<TestCacheSymbolRecord> Cache; // 符号优化 TESTERCACHE<ExpTradeSummary> Cache; // 标准优化 if (Cache.Load(Bytes)) // 读取优化缓存。
请澄清问题。在文章中,SingleTesterCache 和 TesterCache 已经连接。
我想运行 EX5,它将自动获取最后一个 opt/tst 文件(Tester 中最后执行的相应任务)进行分析。
我想运行 EX5,它将自动获取最后一个 opt/tst 文件(在 Tester 中最后执行的相应作业)进行分析。
下面是一个单独运行的变体。
//+------------------------------------------------------------------+ //|TSTcube.mqh //|版权 (c) 2020, Marketeer || //|https://www.mql5.com/en/users/marketeer| //| 交易超立方体的在线分析处理 //|https://www.mql5.com/zh/articles/6602| //|https://www.mql5.com/zh/articles/6603| //|https://www.mql5.com/zh/articles/7656| //|rev.5.03.2020 | //+------------------------------------------------------------------+ #include "ReportCubeBase.mqh" #include <fxsaber/SingleTesterCache/SingleTesterCache.mqh> #include <fxsaber/MultiTester/MTTester.mqh> // + class TesterDeal: public Deal { public: TesterDeal(const TradeDeal &td) { time = (datetime)td.time_create + TimeShift; price = td.price_open; string t = dealType(td.action); type = t == "buy" ? +1 : (t == "sell" ? -1 : 0); t = dealDir(td.entry); direction = 0; if(StringFind(t, "in") > -1) ++direction; if(StringFind(t, "out") > -1) --direction; volume = (double)td.volume; profit = td.profit; deal = (long)td.deal; order = (long)td.order; comment = td.comment[]; symbol = td.symbol[]; commission = td.commission; swap = td.storage; // 余额 - SingleTesterCache.Deals[i].reserve } static string dealType(const ENUM_DEAL_TYPE type) { return type == DEAL_TYPE_BUY ? "buy" : (type == DEAL_TYPE_SELL ? "sell" : "balance"); } static string dealDir(const ENUM_DEAL_ENTRY entry) { string result = ""; if(entry == DEAL_ENTRY_IN) result += "in"; else if(entry == DEAL_ENTRY_OUT || entry == DEAL_ENTRY_OUT_BY) result += "out"; else if(entry == DEAL_ENTRY_INOUT) result += "in out"; return result; } }; template<typename T> class TesterReportAdapter: public BaseReportAdapter<T> { protected: SINGLETESTERCACHE *ptrSingleTesterCache; virtual bool fillDealsArray() override { for(int i = 0; i < ArraySize(ptrSingleTesterCache.Deals); i++) { if(TesterDeal::dealType(ptrSingleTesterCache.Deals[i].action) == "balance") { balance += ptrSingleTesterCache.Deals[i].profit; } else { array << new TesterDeal(ptrSingleTesterCache.Deals[i]); } } return true; } public: ~TesterReportAdapter() { if(CheckPointer(ptrSingleTesterCache) == POINTER_DYNAMIC) delete ptrSingleTesterCache; } virtual bool load(const string file) override { if(StringFind(file, ".tst") > 0) { BaseReportAdapter<T>::load(file); if(CheckPointer(ptrSingleTesterCache) == POINTER_DYNAMIC) delete ptrSingleTesterCache; bool loaded = true; // + ptrSingleTesterCache = new SINGLETESTERCACHE(); if(file == "*.tst") // + { // + uchar Bytes2[]; // + // 为什么 MTTESTER::GetLastTstCacheFileName() 是私有的? // Print("Loading ", MTTESTER::GetLastTstCacheFileName()); // + if(MTTESTER::GetLastTstCache(Bytes2) != -1) // + { // + loaded = ptrSingleTesterCache.Load(Bytes2); // + } // + } else { loaded = ptrSingleTesterCache.Load(file); // * } if(!loaded) // * { delete ptrSingleTesterCache; ptrSingleTesterCache = NULL; return false; } size = generate(); Print("Tester cache import: ", size, " trades from ", ArraySize(ptrSingleTesterCache.Deals), " deals"); } return true; } }; TesterReportAdapter<RECORD_CLASS> _defaultTSTReportAdapter;
我想将最后一个 tst 文件的名称输出到日志中,但相应的方法是私有的。
在设置中应选择文件 "*.tst"(空文件名仍可启动在线账户历史分析)。
#include <fxsaber/MultiTester/MTTester.mqh> // + ... template<typename T> class OptCacheDataAdapter: public DataAdapter { private: TESTERCACHE<ExpTradeSummary> Cache; ... public: OptCacheDataAdapter() { reset(); } void load(const string optName) { bool loaded = true; // + if(optName == "") // + { // + uchar Bytes[]; // + // 为什么 GetLastOptCacheFileName() 是私有的? // + // Print("Loading ", MTTESTER::GetLastOptCacheFileName()); // + MTTESTER::GetLastOptCache(Bytes); // + loaded = Cache.Load(Bytes); // + } else { loaded = Cache.Load(optName); // * } if(loaded) // * { customize(); reset(); } else { cursor = -1; } } ...
我喜欢这篇文章,也喜欢所有关于 OLAP 技术的文章。
就我个人而言,我缺乏思想的飞跃,缺乏对本质的哲学表述,缺乏对整个方法的理解,缺乏对任务和潜力所涵盖的空间的理解。而潜力是巨大的。我对浪费读者时间的多种无关紧要的细节感到痛心。他们说--那里有这样一个变量,这里也有这样一个变量.....。我知道这对于抄袭解决方案的初学者来说是必要的,但....。任何技术都不是一成不变的,如果现在使用你的类和方法,那么将来就会有人想为自己改变一切,对他来说,文章的实用性就会随着私有实体的数量成比例地减少。多写一些关于整体方法的内容--关于它的现在和未来。你需要对这种方法有更全面的认识。
不过,这只是我的主观看法。感谢您的文章。
我想把最后一个 tst 文件的名称输出到日志中,但相应的方法是私有的。
我没想到有人会需要它。如果你对 private->public 有更多意见,请告诉我。我会的。
先生,您好、
我尝试编译文件 "OLAPGUI_Opts.mq5",但在一些包含文件中出现了 17 个错误。
谨致问候,
Ben
新文章 在交易中应用 OLAP(第四部分):定量和可视化分析测试器报告已发布:
本文提供的的基本工具,可针对测试器报告的单次通关验证和优化结果进行 OLAP 分析。 该工具可以操控标准格式文件(tst 和 opt),并还提供了图形界面。 MQL 源代码附带于后。
要以 100 为增量按等级查看利润的一般分布,沿 X 轴的统计信息中选择 “profit” 字段,并选择 “count” 聚合器。
按范围的所有利润分布,增量为 100 单位
利用 “identity” 聚合器,我们可以评估交易数量对利润的影响。 通常,此聚合器可以对许多其他依赖性进行直观评估。
利润与交易数量
作者:Stanislav Korotky