- 显示:
- 138
- 等级:
- 已发布:
-
需要基于此代码的EA交易或指标吗?请在自由职业者服务中订购 进入自由职业者服务
此专家顾问代码将扫描用户经纪人的市场观察并提取符号,下载所有可用的刻度线或截至日期的刻度线。
它可以帮助您下载所有符号历史记录进行回溯测试,或根据这些刻度线创建自定义图表。
终端会将刻度点缓存在数据文件夹中,因此请确保有足够的硬盘空间。
为方便下载符号,我们首先需要一个下载管理器。
结构 CDownloadManager 包含我们需要保留的所有信息。
struct CDownloadManager { bool m_started,m_finished; string m_symbols[],m_current; int m_index;
- 下载状态(开始/完成)
- 要扫描的符号列表
- 当前符号
- 以及正在扫描的符号的索引
我们还需要读取和写入硬盘,由于我们使用的是符号,因此我们创建了 2 个快速函数,用于从二进制文件中写入和读取字符串。
将字符串保存到文件函数:
void writeStringToFile(int f,string thestring) { //保存符号字符串 char sysave[]; int charstotal=StringToCharArray(thestring,sysave,0,StringLen(thestring),CP_ACP); FileWriteInteger(f,charstotal,INT_VALUE); for(int i=0;i<charstotal;i++) { FileWriteInteger(f,sysave[i],CHAR_VALUE); } }
它接收 :
- 文件句柄f、已打开供写入的文件和二进制标志FILE_WRITE|FILE_BIN
- 要写入文件的字符串
写入字符串中字符个数的整数长度,然后将每个字符存储到字符串中。
从文件加载字符串函数:
string readStringFromFile(int f) { string result=""; //load symbol string char syload[]; int charstotal=(int)FileReadInteger(f,INT_VALUE); if(charstotal>0) { ArrayResize(syload,charstotal,0); for(int i=0;i<charstotal;i++) { syload[i]=(char)FileReadInteger(f,CHAR_VALUE); } result=CharArrayToString(syload,0,charstotal,CP_ACP); } return(result); }
它接收
- 以二进制形式打开用于读取的文件句柄 f , 标志 FILE_READ|FILE_BIN
它读取一个整数长度,该长度表示在文件中的这一点有多少个字符。它继续将每个字符读入一个字符数组,然后从该字符数组中创建一个字符串,并将字符串作为字符串加载的结果返回。
回到 CDownloadManager 结构。我们需要一种方法来初始化管理器,并从市场观察中填充它:
//+------------------------------------------------------------------+ //| 从市场观察中抓取符号| //+------------------------------------------------------------------+ void grab_symbols() { //仅从 MW ! int s=SymbolsTotal(true); ArrayResize(m_symbols,s,0); for(int i=0;i<ArraySize(m_symbols);i++) { m_symbols[i]=SymbolName(i,true); } }
非常简单:
- 询问市场观察(活跃)中有多少符号
- 调整 m_symbols 数组的大小,以接收这些符号
- 循环到符号总数中,并请求符号名称
我们还负责管理符号数据的下载,因此我们需要一个函数作为管理器:
//+------------------------------------------------------------------+ //| 管理下载符号进程| //+------------------------------------------------------------------+ void manage(string folder,string filename) { //基本上,这将启动或导航到下一个符号 //if set if(ArraySize(m_symbols)>0) { //if not started if(!m_started) { m_started=true; //转到第一个符号 m_current=m_symbols[0]; m_index=1; save(folder,filename); if(_Symbol!=m_current) { ChartSetSymbolPeriod(ChartID(),m_current,_Period); } else { ENUM_TIMEFRAMES new_period=PERIOD_M1; for(int p=0;p<ArraySize(TFS);p++) { if(_Period!=TFS[p]) { new_period=TFS[p]; break; } } ChartSetSymbolPeriod(ChartID(),m_current,new_period); } return; } //if started else { m_index++; if(m_index<=ArraySize(m_symbols)) { m_current=m_symbols[m_index-1]; save(folder,filename); if(_Symbol!=m_current) { ChartSetSymbolPeriod(ChartID(),m_current,_Period); } return; } else { m_finished=true; FileDelete(folder+"\\"+filename); Print("Finished"); ExpertRemove(); return; } } } else { Print("Please grab symbols first"); } //if set ends here }
系统如何运行:
- 打开图表,我们需要 1 个图表,并设置一个计时器。
- 定时器执行,我们取消定时器
- 检查是新下载还是继续下载
- 如果是新下载,我们通过抓取所有符号进行设置
- 如果是继续下载,我们下载当前符号的数据
这部分代码在定时器上进行下载:
//+------------------------------------------------------------------+ //| 定时器| //+------------------------------------------------------------------+ void OnTimer() { //--- 如果同步 if(SymbolIsSynchronized(_Symbol)&&TerminalInfoInteger(TERMINAL_CONNECTED)==1) { EventKillTimer(); //--- 在此加载系统 if(MANAGER.load(MANAGER_FOLDER,MANAGER_STATUS_FILE)) { //--- 系统已加载,因此我们在这里扫描一个符号 Comment("System loaded and we are processing "+MANAGER.m_current); //--- 标记加载 //--- 先找到经纪商中可用的最老的刻度线 int attempts=0; int ping=-1; datetime cursor=flatten(TimeTradeServer()); long cursorMSC=((long)cursor)*1000; long jump=2592000000;//60*60*24*30*1000; MqlTick receiver[]; long oldest=LONG_MAX; Comment("PleaseWait"); while(attempts<5) { ping=CopyTicks(_Symbol,receiver,COPY_TICKS_ALL,cursorMSC,1); if(ping==1) { if(receiver[0].time_msc==oldest) { attempts++; } else { attempts=0; } if(receiver[0].time_msc<oldest) { oldest=receiver[0].time_msc; } cursorMSC-=jump; if(limitDate&&receiver[0].time<=oldestLimit) { break; } } else { attempts++; } Sleep(44); Comment("Oldest Tick : "+TimeToString((datetime)(oldest/1000),TIME_DATE|TIME_MINUTES|TIME_SECONDS)+"\nCursor("+TimeToString((datetime)(cursorMSC/1000),TIME_DATE|TIME_MINUTES|TIME_SECONDS)+")\nAttempts("+IntegerToString(attempts)+")\nPlease wait for response..."); } //---------------------此时我们有了最老的刻度 //-----------------开始从最旧到最新请求刻度 if(oldest!=LONG_MAX) { ArrayFree(receiver); datetime newest_tick=0; //--- 接收存储在 symbol_time 中的该符号最后一次跳动的时间 datetime most_recent_candle=(datetime)SymbolInfoInteger(_Symbol,SYMBOL_TIME); while(newest_tick<most_recent_candle) { //--- 申请新的批次,从最旧的时间开始,并指定刻度限制 int pulled=CopyTicks(_Symbol,receiver,COPY_TICKS_ALL,oldest,tick_packets); if(pulled>0) { //--- 如果我们提取新的批次,更新我们的下载时间 newest_tick=receiver[pulled-1].time; oldest=receiver[pulled-1].time_msc; ArrayFree(receiver); } //--- 服务器请求超时,如果需要可以修改 Sleep(44); Comment("Pulled up to "+TimeToString(newest_tick,TIME_DATE|TIME_MINUTES|TIME_SECONDS)+" so far"); } } else { Alert("Please close the terminal \n head over to the ticks folder \n and delete the empty folders"); ExpertRemove(); } //--- 更新管理器并继续 MANAGER.manage(MANAGER_FOLDER,MANAGER_STATUS_FILE); } else { //--- 抓取市场观察符号开始下载 Comment("Grabbing MW and starting"); MANAGER.grab_symbols(); MANAGER.manage(MANAGER_FOLDER,MANAGER_STATUS_FILE); } } }
由MetaQuotes Ltd译自英文
原代码: https://www.mql5.com/en/code/56324

MACD 彩色柱状图是经典 MACD(移动平均收敛背离)指标的增强版,旨在提供更清晰、更直观的市场动量视觉分析。该指标将传统的 MACD 功能与动态柱状图相结合,根据 MACD 线与信号线之间的关系改变颜色,使交易者能够快速识别趋势、反转点和市场中的犹豫不决时刻。

无论您是同时运行多个交易机器人,还是只运行一个复杂的策略,跟踪每个智能交易系统的表现都会非常耗时。MetaTrader 5(MT5)可以在 "工具箱 "中方便地显示订单和头寸,但当多个机器人共享同一个账户时,就很难知道哪个 EA 为您带来了利润或损失。一个账户可能有数十或数百笔交易,每笔交易都由不同的 EA 开立,因此很难将一个机器人的结果与另一个机器人的结果区分开来。

这些 #define 语句对在 EA 中执行操作非常有用。您只需在文件开头指定变量的名称,然后让其他 #define 语句完成工作。 要使用此文件,请在 EA 文件的第一行添加 #include<DEFINE_statements.mqh> 。

该指标绘制两条线。下线根据导致反弹的最新 SMA 周期计算。上线根据导致反弹下跌的最近 SMA 周期计算。