如何利用 MQL5 创建简单的多币种智能交易系统(第 1 部分):基于 ADX 指标的信号,并结合抛物线 SAR·进阶篇
📘

如何利用 MQL5 创建简单的多币种智能交易系统(第 1 部分):基于 ADX 指标的信号,并结合抛物线 SAR·进阶篇

第 2/3 篇

「EA 头文件里的全局变量与函数声明骨架」

这段声明块通常出现在 MQL5 多品种 EA 的顶层 include 或主文件开头,先把跨周期、跨品种要复用的变量一次性摊开。 pip、xpip 存点值换算结果,floatprofit 与 fixclprofit 分别记浮动与已锁定的利润;ADXDIp[]、ADXDIm[] 是两个双精度数组,用来接 ADX 指标的 +DI 与 -DI 线,后续判断交叉直接用下标取数。 pairs、hariini、daytrade、trade_mode 是字符串型开关,控制交易品种集合、日内起始、是否日内模式与下单逻辑分支;OPEN[] HIGH[] LOW[] CLOSE[] TIME[] 则是 OHLC 与时间的行情缓存数组,closetime 单独记平仓时刻。 函数声明部分暴露了策略的真实构件:iADXCross 看 ADX 方向线交叉,iADXpct 取某 index 的 ADX 百分比强度,PARSAR05/15/Op 是三个不同周期或启动参数的 SAR 通道判断;LotDig 与 MLots 管手数精度与计算,NonZeroDiv 防除零。 挂单与持仓的止损止盈由 OrderSLSet / OrderTPSet / SetOrderSL / SetOrderTP 按订单或持仓类型分流,TSPrice 做追踪止损价计算,TS_type 区分几种 trailing 逻辑;最后 ReqDate(d,h,m) 把日时分拼成请求用的时间串,方便回测或定时触发。 在 MT5 里把这块直接贴进一个新 include 文件,编译若报 ENUM_ORDER_TYPE 未定义,说明少引了 Trade 相关标准库,补 #include <Trade/Trade.mqh> 即可。外汇与贵金属杠杆高,这类全局变量若在多品种上同时跑,要注意内存与 tick 占用。

MQL5 / C++
              pip,
              xpip;
   class="type">class="kw">double              floatprofit,
                      fixclprofit;
   class="type">class="kw">double              ADXDIp[];
   class="type">class="kw">double              ADXDIm[];
   class=class="str">"cmt">//--
   class="type">class="kw">string              pairs,
                      hariini,
                      daytrade,
                      trade_mode;
   class=class="str">"cmt">//--
   class="type">class="kw">double              OPEN[],
                      HIGH[],
                      LOW[],
                      CLOSE[];
   class="type">class="kw">datetime            TIME[];
   class="type">class="kw">datetime            closetime;
   class=class="str">"cmt">//--
   class=class="str">"cmt">//------------
   class=class="str">"cmt">//------------
   class="type">int                 iADXCross(const class="type">class="kw">string symbol);
   class="type">int                 iADXpct(const class="type">class="kw">string symbol,const class="type">int index);
   class="type">int                 PARSAR05(const class="type">class="kw">string symbol);
   class="type">int                 PARSAR15(const class="type">class="kw">string symbol);
   class="type">int                 PARSAROp(const class="type">class="kw">string symbol);
   class="type">int                 LotDig(const class="type">class="kw">string symbol);
   class=class="str">"cmt">//--
   class="type">class="kw">double              MLots(const class="type">class="kw">string symbx);
   class="type">class="kw">double              NonZeroDiv(class="type">class="kw">double val1,class="type">class="kw">double val2);
   class="type">class="kw">double              OrderSLSet(const class="type">class="kw">string xsymb,ENUM_ORDER_TYPE type,class="type">class="kw">double atprice);
   class="type">class="kw">double              OrderTPSet(const class="type">class="kw">string xsymb,ENUM_ORDER_TYPE type,class="type">class="kw">double atprice);
   class="type">class="kw">double              SetOrderSL(const class="type">class="kw">string xsymb,class="type">ENUM_POSITION_TYPE type,class="type">class="kw">double atprice);
   class="type">class="kw">double              SetOrderTP(const class="type">class="kw">string xsymb,class="type">ENUM_POSITION_TYPE type,class="type">class="kw">double atprice);
   class="type">class="kw">double              TSPrice(const class="type">class="kw">string xsymb,class="type">ENUM_POSITION_TYPE ptype,class="type">int TS_type);
   class=class="str">"cmt">//--
   class="type">class="kw">string              ReqDate(class="type">int d,class="type">int h,class="type">int m);

◍ EA 配置结构里的成员布局

这段声明来自一个 ADX+PSAR 复合策略 EA 的类定义,把周期、手句柄、参数数组全部摊在 public 区,方便外部直接读写与调试。 TFt、TFT15、TFT05 三个 ENUM_TIMEFRAMES 变量分别对应主图、15 分钟、5 分钟周期;hParOp、hPar15、hPar05 则是三个周期下 PSAR 指标的句柄数组,若句柄为 INVALID_HANDLE 则指标调用会直接失效。 profitb[] 与 profits[] 是 double 型数组,用来存突破与止损位的缓冲值;Buy、Sell 为 int 计数,记录当前多空挂单或持仓数量。year~sec 这一组 int 只是把 TimeCurrent 拆开存,方便按交易时段过滤。 在 MT5 里把这类结构直接 public 会牺牲封装性,但回测时你可以用 iCustom 或脚本直接打印 expname、slip、SARstep 来确认参数生效,外汇与贵金属波动剧烈,参数误读可能导致滑点远超预期。

MQL5 / C++
class="type">class="kw">string TF2Str(ENUM_TIMEFRAMES period);
class="type">class="kw">string timehr(class="type">int hr,class="type">int mn);
class="type">class="kw">string TradingDay(class="type">void);
class="type">class="kw">string AccountMode();
class="type">class="kw">string GetCommentForOrder(class="type">void) { class="kw">return(expname); }
class=class="str">"cmt">//------------
class="kw">public:
class=class="str">"cmt">//-- ADXPSAR_MCEA Config --
class="type">class="kw">string DIRI[],
       AS30[];
class="type">class="kw">string expname;
class="type">int handADX[];
class="type">int hParOp[],
    hPar15[],
    hPar05[];
class="type">int ALO,
    dgts,
    arrsymbx;
class="type">int sall,
    arper;
class="type">ulong slip;
ENUM_TIMEFRAMES TFt,
       TFT15,
       TFT05;
class=class="str">"cmt">//--
class="type">class="kw">double SARstep,
       SARmaxi;
class="type">class="kw">double profitb[],
       profits[];
class=class="str">"cmt">//--
class="type">int Buy,
    Sell;
class="type">int ccur,
    psec,
    xtto,
    checktml;
class="type">int OpOr[],xob[],xos[];
class=class="str">"cmt">//--
class="type">int year, class=class="str">"cmt">// Year
    mon,  class=class="str">"cmt">// Month
    day,  class=class="str">"cmt">// Day
    hour, class=class="str">"cmt">// Hour
    min,  class=class="str">"cmt">// Minutes
    sec;  class=class="str">"cmt">// Seconds

EA 类骨架里的日期字段与交易动作接口

这段 MQL5 代码露出了自定义 EA 类 MCEA 的成员变量与函数声明轮廓。两个整型变量 dow 与 doy 专门承接时间维度:dow 记录星期几(0 为周日,6 为周六),doy 记录年内第几天(1 月 1 日从 0 算起),做跨周期过滤时直接读这两个值比反复调 TimeDayOfWeek 更省。 类里把交易相关动作拆得很碎:OpenBuy / OpenSell 只负责开仓,CloseBuyPositions / CloseSellPositions / CloseAllOrders 分管平仓,ModifySLTP 与 ModifyOrderSLTP 管止损止盈重设。这种拆分让你在 ExpertActionTrade 里能按信号组合调用,而不是写一坨耦合逻辑。 bool 型函数返回执行结果,方便上层判断今天 TradingToday 是否放行、RefreshTick 是否拿到新报价。外汇与贵金属波动剧烈、杠杆高风险,任何自动交易接口在 MT5 策略测试器里跑过历史数据前,都只能当作概率工具,别直接挂真仓。

MQL5 / C++
class="type">int dow, class=class="str">"cmt">// Day of week(class="num">0-Sunday, class="num">1-Monday, ... ,class="num">6-Saturday)
class="type">int doy; class=class="str">"cmt">// Day number of the year(January 1st is assigned the number value of zero)
class=class="str">"cmt">//------------
MCEA(class="type">void);
~MCEA(class="type">void);
class=class="str">"cmt">//------------
class=class="str">"cmt">//--
class="kw">virtual class="type">void ADXPSAR_MCEA_Config(class="type">void);
class="kw">virtual class="type">void ExpertActionTrade(class="type">void);
class=class="str">"cmt">//--
class="type">void ArraySymbolResize(class="type">void);
class="type">void CurrentSymbolSet(const class="type">class="kw">string symbol);
class="type">void Pips(const class="type">class="kw">string symbol);
class="type">void TradeInfo(class="type">void);
class="type">void Do_Alerts(const class="type">class="kw">string symbx,class="type">class="kw">string msgText);
class="type">void CheckOpenPMx(const class="type">class="kw">string symbx);
class="type">void SetSLTPOrders(class="type">void);
class="type">void CloseBuyPositions(const class="type">class="kw">string symbol);
class="type">void CloseSellPositions(const class="type">class="kw">string symbol);
class="type">void CloseAllOrders(class="type">void);
class="type">void CheckClose(const class="type">class="kw">string symbx);
class="type">void TodayOrders(class="type">void);
class="type">void UpdatePrice(const class="type">class="kw">string symbol,ENUM_TIMEFRAMES xtf);
class="type">void RefreshPrice(const class="type">class="kw">string symbx,ENUM_TIMEFRAMES xtf,class="type">int bars);
class=class="str">"cmt">//--
class="type">bool RefreshTick(const class="type">class="kw">string symbx);
class="type">bool TradingToday(class="type">void);
class="type">bool OpenBuy(const class="type">class="kw">string symbol);
class="type">bool OpenSell(const class="type">class="kw">string symbol);
class="type">bool ModifyOrderSLTP(class="type">class="kw">double mStop,class="type">class="kw">double ordtp);
class="type">bool ModifySLTP(const class="type">class="kw">string symbx,class="type">int TS_type);
class="type">bool CloseAllProfit(class="type">void);

「多币种EA的初始化与品种注册」

多币种机器人启动靠 OnInit() 完成配置装载,里面只调一句 mc.ADXPSAR_MCEA_Config() 就返回 INIT_SUCCEEDED,真正的品种池在类方法里落地。 配置函数里先声明一个 30 元素的字符串数组 All30[],覆盖 EURUSD、GBPUSD 到 XAUUSD、XAGUSD 等 7 个直盘、21 个交叉盘加黄金白银,把外汇与贵金属放在同一池子里跑。 sall 用 ArraySize(All30) 取到 30,再 ArrayResize(AS30,sall,sall) 把动态数组 AS30 一次性扩到同等长度,后续面板按钮切图、切品种都读这块内存。 类尾巴还挂了 ManualCloseAllProfit、PairsIdxArray、DirectionMove 等 9 个方法声明,负责平仓、索引、弱信号退出等逻辑,初始化阶段不触发,只在 tick 中按需调用。 开 MT5 把 All30 改成你实盘允许交易的 12 对,能明显降算力占用;贵金属波动大,多币种同跑须自担隔夜跳空高风险。

MQL5 / C++
class="type">bool                 ManualCloseAllProfit(class="type">void);
class=class="str">"cmt">//--
class="type">int                  PairsIdxArray(const class="type">class="kw">string symbol);
class="type">int                  GetOpenPosition(const class="type">class="kw">string symbol);
class="type">int                  DirectionMove(const class="type">class="kw">string symbol);
class="type">int                  GetCloseInWeakSignal(const class="type">class="kw">string symbol,class="type">int exis);
class="type">int                  CheckToCloseInWeakSignal(const class="type">class="kw">string symbol,class="type">int exis);
class="type">int                  ThisTime(const class="type">int reqmode);
class=class="str">"cmt">//--
class="type">class="kw">string               getUninitReasonText(class="type">int reasonCode);
class=class="str">"cmt">//--
class=class="str">"cmt">//------------
class=class="str">"cmt">//---
}; class=class="str">"cmt">//-end class MCEA
class=class="str">"cmt">//---------//
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Expert initialization function                                     |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">int OnInit(class="type">void)
  {
class=class="str">"cmt">//---
  mc.ADXPSAR_MCEA_Config();
class=class="str">"cmt">//--
  class="kw">return(INIT_SUCCEEDED);
class=class="str">"cmt">//---
  } class=class="str">"cmt">//-end OnInit()
class=class="str">"cmt">//---------//
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Expert Configuration                                              |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">void MCEA::ADXPSAR_MCEA_Config(class="type">void)
  {
class=class="str">"cmt">//---
class=class="str">"cmt">//-- Here we will register all the symbols or pairs that will be used on the Multi-Currency Expert Advisor
class=class="str">"cmt">//--
  class="type">class="kw">string All30[]= {"EURUSD","GBPUSD","AUDUSD","NZDUSD","USDCAD","USDCHF","USDJPY","EURGBP",
                   "EURAUD","EURNZD","EURCAD","EURCHF","EURJPY","GBPAUD","GBPNZD","GBPCAD",
                   "GBPCHF","GBPJPY","AUDNZD","AUDCAD","AUDCHF","AUDJPY","NZDCAD","NZDCHF",
                   "NZDJPY","CADCHF","CADJPY","CHFJPY","XAUUSD","XAGUSD"
                    }; class=class="str">"cmt">// class="num">30 pairs
class=class="str">"cmt">//--
  sall=ArraySize(All30);
  ArrayResize(AS30,sall,sall);
class=class="str">"cmt">//-- These AS30[] arrays will be used in the symbol list panel and for the buttons to change symbols and charts

◍ 多币种 EA 的初始化与 tick 触发骨架

多币种策略在 MT5 里第一道坎不是信号,而是把市场报价窗口里的品种全部拉进交易上下文。上面这段代码先用 ArrayCopy 把已筛选的 30 个品种名塞进 DIRI[],再跑一个 for 循环对每个 DIRI[x] 调用 SymbolSelect(...,true),否则后续 iADX / iSAR 拿不到句柄。 时间框架不能写死。代码里用 TFs[] 存了 8 个周期:从 PERIOD_H1 到 PERIOD_D1,再用输入的 TimeFrames 整型索引去匹配 TFt。你改 EA 输入里的 TimeFrames=3,实际信号周期就落到了 PERIOD_H4,这种映射方式比硬编码 PERIOD_H4 更方便回测切换。 句柄必须按品种逐个建。循环里给每个品种同时挂了 iADX(当前 TFt)和三个 iSAR(TFt、M15、M5),说明策略可能用多周期 SAR 交叉过滤 ADX 方向。注意 hPar15 / hPar05 用的是独立周期变量,若你只做单周期,可以把这两行删掉省资源。 券商对总持仓品种数有限制。代码用 mc_account.LimitOrders() 和 arrsymbx 取小值赋给 ALO,避免开仓时撞上错误码 10040(TRADE_RETCODE_LIMIT_POSITIONS)。外汇与贵金属保证金交易杠杆高,实盘前务必在策略测试器用「全部品种」模式跑一遍,确认 ALO 逻辑不会在的第 31 个品种上静默跳过。 OnTick 本身极薄,只调了 mc.ExpertActionTrade() 就返回。真正的下单、平仓、风控都封装在那个多币种交易类里,这种结构方便你把配置函数和逐 tick 逻辑解耦,改参数不用动主循环。

MQL5 / C++
  ArrayCopy(AS30,All30,class="num">0,class="num">0,WHOLE_ARRAY);
class=class="str">"cmt">//--
  arrsymbx=sall;
  ArraySymbolResize();
  ArrayCopy(DIRI,All30,class="num">0,class="num">0,WHOLE_ARRAY); class=class="str">"cmt">//-- The "DIRI[]" array containing the symbol or pair name will be used
class=class="str">"cmt">//-- in all trading activities of the multi-currency expert
class=class="str">"cmt">//--
class=class="str">"cmt">//-- This function is for Select all symbol in the Market Watch window
  for(class="type">int x=class="num">0;x<arrsymbx; x++)
    {
      SymbolSelect(DIRI[x],true);
    }
  pairs="Multi Currency class="num">30 Pairs";
class=class="str">"cmt">//---
class=class="str">"cmt">//-- Here we will provide a Period Timeframe value which will be used for signal calculations according
class=class="str">"cmt">//-- to the Timeframe option on the expert class="kw">input class="kw">property.
  ENUM_TIMEFRAMES TFs[]= {PERIOD_H1,PERIOD_H2,PERIOD_H3,PERIOD_H4,PERIOD_H6,PERIOD_H8,PERIOD_H12,PERIOD_D1};
  class="type">int arTFs=ArraySize(TFs);
  for(class="type">int x=class="num">0; x<arTFs; x++)
    {
      if(x==TimeFrames)
        {
         TFt=TFs[x];
         break;
        }
    }
class=class="str">"cmt">//--
class=class="str">"cmt">//-- Indicators handle for all symbol
  for(class="type">int x=class="num">0; x<arrsymbx; x++)
    {
     handADX[x]=iADX(DIRI[x],TFt,ADXPeriod);          class=class="str">"cmt">//-- Handle for the iADX indicator according to the selected Timeframe
     hParOp[x]=iSAR(DIRI[x],TFt,SARstep,SARmaxi);     class=class="str">"cmt">//-- Handle for the iSAR indicator according to the selected Timeframe
     hPar15[x]=iSAR(DIRI[x],TFT15,SARstep,SARmaxi);   class=class="str">"cmt">//-- Handle for the iSAR indicator for M15 Timeframe
     hPar05[x]=iSAR(DIRI[x],TFT05,SARstep,SARmaxi);   class=class="str">"cmt">//-- Handle for the iSAR indicator for M5 Timeframe
    }
class=class="str">"cmt">//--
class=class="str">"cmt">//-- Since this expert advisor is a multi-currency expert, we must check the maximum number
class=class="str">"cmt">//-- of account limit orders allowed by the broker.
class=class="str">"cmt">//-- This needs to be checked, so that when the expert opens an order there will be
class=class="str">"cmt">//-- no class="kw">return codes of the trade server error class="num">10040 = TRADE_RETCODE_LIMIT_POSITIONS
  ALO=(class="type">int)mc_account.LimitOrders()>arrsymbx ? arrsymbx : (class="type">int)mc_account.LimitOrders();
class=class="str">"cmt">//--
class=class="str">"cmt">//-- The LotPS variable will later be used for the proportional distribution of Lot sizes for each symbol
  LotPS=(class="type">class="kw">double)ALO;
class=class="str">"cmt">//--
  mc_trade.SetExpertMagicNumber(magicEA); class=class="str">"cmt">//-- Set Magic Number as expert ID
  mc_trade.SetDeviationInPoints(slip);    class=class="str">"cmt">//-- Set expert deviation with slip variable value
  mc_trade.SetMarginMode();               class=class="str">"cmt">//-- Set the Margin Mode expert to the value of Account Margin Mode
class=class="str">"cmt">//--
  class="kw">return;
class=class="str">"cmt">//---
  } class=class="str">"cmt">//-end ADXPSAR_MCEA_Config()
class=class="str">"cmt">//---------//
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Expert tick function                                             |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">void OnTick(class="type">void)
  {
class=class="str">"cmt">//---
  mc.ExpertActionTrade();
class=class="str">"cmt">//--
  class="kw">return;
class=class="str">"cmt">//---
  } class=class="str">"cmt">//-end OnTick()

多币种EA的5秒轮询与终端校验

多币种EA在MT5里跑,第一步不是算信号,而是确认终端允许算法交易。代码里用 MQLInfoInteger(MQL_TRADE_ALLOWED) 做闸门,若禁止且标记位 checktml 为0,就弹一次 alert 并 return,避免每 tick 刷屏报警。 不同品种 SymbolInfoTick 的报价频率不一致,若每个 tick 都全市场扫信号,CPU 会被拖死。原文把轮询降频到每 5 秒一次:用 fmod((double)mcsec,5.0)==0 判定秒数走到 5 的整数倍,再把当前秒存进 mc.ccur,只有 mc.ccur!=mc.psec 才进交易逻辑。 进入逻辑后是一个 for 循环遍历 mc.arrsymbx 个品种,配合 !IsStopped() 防止 EA 被手动停止时还发单。外汇与贵金属多币种自动化波动剧烈、滑点扩大,实盘前务必在策略测试器用真实点差回测,并确认「允许算法交易」已勾选,否则 EA 可能静默不交易。

MQL5 / C++
class="type">void MCEA::ExpertActionTrade(class="type">void)
  {
class=class="str">"cmt">//---
    class=class="str">"cmt">//Check Trading Terminal
    ResetLastError();
    class=class="str">"cmt">//--
    if(!MQLInfoInteger(MQL_TRADE_ALLOWED) && mc.checktml==class="num">0) class=class="str">"cmt">//-- Check whether MT5 Algorithmic trading is Allow or Prohibit
      {
        mc.Do_Alerts(Symbol(),"Trading Expert at "+Symbol()+" are NOT Allowed by Setting.");
        mc.checktml=class="num">1;  class=class="str">"cmt">//-- Variable checktml is given a value of class="num">1, so that the alert is only done once.
        class="kw">return;
      }
    class=class="str">"cmt">//--
    if(!DisplayManualButton("M","C","R"))
      DisplayManualButton(); class=class="str">"cmt">//-- Show the expert manual button panel
    class=class="str">"cmt">//--
    class=class="str">"cmt">//-- The functions below will be displayed on the expert chart according to
    class=class="str">"cmt">//-- the Select Display Trading Info on Chart(Yes) or(No) option on expert class="kw">property.
    class=class="str">"cmt">//--
    if(trade_info_display==Yes)
      mc.TradeInfo(); class=class="str">"cmt">//-- Displayed Trading Info on Chart
class=class="str">"cmt">//--
    class=class="str">"cmt">//--
    if(trade_info_display==Yes) mc.TradeInfo(); class=class="str">"cmt">//-- Displayed Trading Info on Chart
    class=class="str">"cmt">//---
    class=class="str">"cmt">//--
    class=class="str">"cmt">//-- Because the current prices of a specified symbol(SymbolInfoTick) will occur differently
    class=class="str">"cmt">//-- for each symbol, we reduce the tick update frequency to only every class="num">5 seconds.
    class=class="str">"cmt">//-- So, looping to check the signal for all trading activity of all symbols will only be done every class="num">5 seconds.
    class=class="str">"cmt">//--
    class="type">int mcsec=mc.ThisTime(mc.sec);
    class=class="str">"cmt">//-- With the function ThisTime(mc.sec), we will retrieve the current seconds value to mcsec variable.
    class=class="str">"cmt">//--
    class=class="str">"cmt">//-- MathMod is a formula that gives the(modulus) real remainder after the division of two numbers.
    class=class="str">"cmt">//-- By dividing the value of seconds with the value of class="num">5.0, if the result is class="num">0, it means that class="num">5 seconds
    class=class="str">"cmt">//-- have been reached from the previous psec variable seconds value.
    class=class="str">"cmt">//--
    if(fmod((class="type">class="kw">double)mcsec,class="num">5.0)==class="num">0)
      mc.ccur=mcsec;
    class=class="str">"cmt">//--
    if(mc.ccur!=mc.psec) class=class="str">"cmt">//-- So, if the seconds value in the ccur variable is not the same as the psec variable value
      {
        class=class="str">"cmt">//-- (then the psec variable value already class="num">5 seconds before)
        class="type">class="kw">string symbol;
        class=class="str">"cmt">//-- Here we start with the rotation of the name of all symbol or pairs to be traded
        class=class="str">"cmt">//-- This is the basic framework for the automated trading workflow of this Multi-Currency Expert Advisor
        class=class="str">"cmt">//-- Here we start with the rotation of the name of all symbol or pairs to be traded
        class=class="str">"cmt">//-- This is the basic framework for the automated trading workflow of this Multi-Currency Expert Advisor
        for(class="type">int x=class="num">0; x<mc.arrsymbx && !IsStopped(); x++)
          {
            class=class="str">"cmt">//--
            if(mc.DIRI[x]==Symbol())

常见问题

先放跨品种共用的全局句柄与配置结构,再把信号计算、交易动作、品种注册都抽成函数声明,类骨架里留日期字段和交易接口即可。
在初始化里建指标句柄、填配置结构、把每个要交易的品种名加进数组并完成句柄绑定,失败就直接返回初始化错误。
可以,小布能读你的EA结构并提示品种注册遗漏、5秒轮询间隔设置异常以及终端校验缺失等常见问题。
5秒轮询能降CPU占用并避免同tick重复下单,配合终端校验可防掉线后逻辑错乱,回测也更稳。
日期字段存最近信号时间,交易接口只暴露开仓平仓函数,内部再按品种和ADX+SAR信号分支,后续加币种不改骨架。