根据指定的分布法则为自定义品种的时间序列建模(基础篇)
「用分布法则给自定义品种造时间序列」
在 MT5 里做策略原型,常苦于历史数据不够或想测极端行情。平台支持自建自定义品种,按指定统计分布给它的时间序列建模,就能绕开真实样本不足的限制。 创建自定义品种用 CustomSymbolCreate,删则用 CustomSymbolDelete,品种名带前缀如 "TEST" 便于区分。建好后先灌入逐笔报价(tick)再聚合成柱线,否则图表不刷新。 模拟趋势时别只丢随机数:用带漂移项的分布(如几何布朗运动近似)才像真行情;单纯正态噪声跑出来是横盘噪声,容易被误判为有效样本。外汇与贵金属杠杆高、跳空频繁,自建序列若忽略滑点层,回测盈利可能虚高,实盘倾向亏损。
◍ 自定义品种能帮你绕开实盘试错
MT5 终端原生支持创建自定义品种,这意味着你可以不接真流动性,也能在策略测试器里跑自己的货币对或贵金属合成标的。对于想验证非常规报价节奏的人,这比开模拟户更干净。 原文给出的思路是按指定分布法则生成逐笔报价与柱线,并能模拟趋势和常见图表形态。配套脚本把最小设置封装好了,不会写 MQL5 的人也能直接调参数生成品种。 外汇与贵金属本身杠杆高、滑点无常,用自定义品种回测出的形态胜率只代表该分布假设下的概率倾向,不能直接外推到实盘。开 MT5 装好脚本,先生成一个正态报价的 EURUSD 合成品种,对比真实 tick 密度,就能看出假设偏离在哪。
在 MT5 里用脚本造一个自己的品种
MT5 的“品种”窗口支持自定义品种,但手动建很麻烦。早期有方案基于已有品种自动生成,这里把它压成最小配置:脚本只要 4 个输入参数——自定义品种名、简称、全称、以及可选的基准品种简称(如 EURUSD)。 脚本先调 CustomSymbolCreate 在 Custom/Forex 下建品种;想换子目录就在第二个参数写组名。建完若没给 BaseName,就按用户输入设属性,否则从基准品种(EURUSD/USDCAD 等)抄属性。属性分字符串、整数、双精度三组写,成功才打印创建成功,否则把错误码丢进日志。 删除比创建更坑:在“品种”标签里选中后往往删不掉,必须先从市场观察移除、关掉所有该品种图表和持仓。下面这版删除脚本会先找品种,试 CustomSymbolDelete,删不动就 SimbolSelect 禁用,再不行就循环关掉所有 SName 图表后重试。注意它不自动平持仓,避免误伤你的实盘。外汇/贵金属自定义品种测试仍属高风险操作,参数错了可能图表异常。 别把基准品种当万能模板:从 EURUSD 抄来的点差、合约大小未必适合你新品种,建完务必人工核对 SymbolInfo 返回的关键属性。
class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| CreateSymbol.mq5 | class=class="str">"cmt">//| Aleksey Zinovik | class=class="str">"cmt">//| | class=class="str">"cmt">//+------------------------------------------------------------------+ class="macro">#class="kw">property copyright "Aleksey Zinovik" class="macro">#class="kw">property script_show_inputs class="macro">#class="kw">property version "class="num">1.00" class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| 脚本程序开始函数 | class=class="str">"cmt">//+------------------------------------------------------------------+ class="kw">input class="type">class="kw">string SName="ExampleCurrency"; class="kw">input class="type">class="kw">string CurrencyName="UCR"; class="kw">input class="type">class="kw">string CurrencyFullName="UserCurrency"; class="kw">input class="type">class="kw">string BaseName="EURUSD"; class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">void OnStart() { ResetLastError(); class=class="str">"cmt">// 创建品种 if(!CustomSymbolCreate(SName,"\\Forex")) { if(SymbolInfoInteger(SName,SYMBOL_CUSTOM)) Print("Symbol ",SName," already exists!"); else Print("Error creating symbol. Error code: ",GetLastError()); } else {
「自定义品种创建时的属性落盘」
在 MT5 里用代码新建一个自定义品种时,先判断 BaseName 为空才走创建分支,避免重复覆盖已有品种。这一节把所有字符串类和整数类属性一次性写进去,是后续报价和图表能跑起来的地基。 字符串类先填基准货币、盈利货币与保证金货币,例子中盈利和保证金都锁死为 USD,基准货币由 CurrencyName 变量带入;描述、底层资产、定价公式、ISIN、网页这些字段先留空串,等后期再补。 整数类才是真正影响盘口观感的参数:图表按竞买价绘制、点差设 3 且标记为浮动、报价精度 5 位、订单簿深度预置 10 档。外汇与贵金属自定义品种高风险,点差和精度设错会直接让回测与实盘偏差放大。 下面这段是原文创建分支的节选,逐行看就是上面说的落盘顺序: if(BaseName=="")// 若基准名空,说明品种还不存在,进入新建 { // 字符串类型属性 if((SetProperty(SName,SYMBOL_CURRENCY_BASE,CurrencyName,"")) && // 写基准货币 (SetProperty(SName,SYMBOL_CURRENCY_PROFIT,"USD",""))&& // 盈利货币 USD (SetProperty(SName,SYMBOL_CURRENCY_MARGIN,"USD",""))&& // 保证金货币 USD (SetProperty(SName,SYMBOL_DESCRIPTION,CurrencyName,""))&& // 品种描述 (SetProperty(SName,SYMBOL_BASIS,"","")) && // 底层资产名 (SetProperty(SName,SYMBOL_FORMULA,"","")) && // 定价公式 (SetProperty(SName,SYMBOL_ISIN,"","")) && // ISIN 名 (SetProperty(SName,SYMBOL_PAGE,"","")) && // 信息网页 // 整数类型属性 (SetProperty(SName,SYMBOL_CHART_MODE,SYMBOL_CHART_MODE_BID,"")) && // 图表按买价 (SetProperty(SName,SYMBOL_SPREAD,3,"")) && // 点差 3 (SetProperty(SName,SYMBOL_SPREAD_FLOAT,true,"")) && // 浮动点差 (SetProperty(SName,SYMBOL_DIGITS,5,"")) && // 精度 5 位 (SetProperty(SName,SYMBOL_TICKS_BOOKDEPTH,10,"")) && // 深度 10 档
if(BaseName=="")class=class="str">"cmt">// create new { class=class="str">"cmt">// 字符串类型属性 if((SetProperty(SName,SYMBOL_CURRENCY_BASE,CurrencyName,"")) && class=class="str">"cmt">// 基准货币 (SetProperty(SName,SYMBOL_CURRENCY_PROFIT,"USD",""))&& class=class="str">"cmt">// 盈利货币 (SetProperty(SName,SYMBOL_CURRENCY_MARGIN,"USD",""))&& class=class="str">"cmt">// 保证金货币 (SetProperty(SName,SYMBOL_DESCRIPTION,CurrencyName,""))&& class=class="str">"cmt">// 品种的字符串描述(全名) (SetProperty(SName,SYMBOL_BASIS,"","")) && class=class="str">"cmt">// 自定义品种的底层资产的名称 (SetProperty(SName,SYMBOL_FORMULA,"","")) && class=class="str">"cmt">// 自定义品种的定价公式 (SetProperty(SName,SYMBOL_ISIN,"","")) && class=class="str">"cmt">// ISIN 系统中交易品种的名称 (SetProperty(SName,SYMBOL_PAGE,"","")) && class=class="str">"cmt">// 包含品种信息的网页 class=class="str">"cmt">// 整数类型属性 (SetProperty(SName,SYMBOL_CHART_MODE,SYMBOL_CHART_MODE_BID,"")) && class=class="str">"cmt">// 按竞买价绘制图表 (SetProperty(SName,SYMBOL_SPREAD,class="num">3,"")) && class=class="str">"cmt">// 点差 (SetProperty(SName,SYMBOL_SPREAD_FLOAT,true,"")) && class=class="str">"cmt">// 浮动点差 (SetProperty(SName,SYMBOL_DIGITS,class="num">5,"")) && class=class="str">"cmt">// 精度 (SetProperty(SName,SYMBOL_TICKS_BOOKDEPTH,class="num">10,"")) && class=class="str">"cmt">// 预置订单深度
◍ 自定义品种的交易属性注入
在 MT5 用 CustomSymbol 系列函数造一个仿真品种时,光有名字和点值不够,必须把交易行为参数一次性写进符号属性里,否则市场观察窗口里它只是个不能下单的空壳。 下面这段连续 SetProperty 调用把背景色、交易权限、执行模式到掉期规则全量设定:SYMBOL_TRADE_MODE 给 FULL 代表完全访问,SYMBOL_TRADE_EXEMODE 设 INSTANT 即即时执行,SYMBOL_FILLING_MODE 用 FOK 意味着要么按价全填要么撤销。 值得盯一眼的是 SYMBOL_ORDER_MODE 传了 127——这是把 7 种基础订单类型的位掩码全打开(1+2+4+8+16+32+64=127),等于允许挂单、止损、止盈全类型。 SYMBOL_SWAP_MODE 设 POINTS 且 ROLLOVER3DAYS 为 WEDNESDAY,说明掉期按点数计、三倍息在周三滚;SYMBOL_TRADE_STOPS_LEVEL 和 FREEZE_LEVEL 都给 0,代表对该符号不强制止损距离与冻结距。外汇与贵金属自定义符号涉及杠杆与保证金,属高风险操作,参数错配可能让回测与实盘偏差极大。
(SetProperty(SName,SYMBOL_BACKGROUND_COLOR,White,""))&& class=class="str">"cmt">// 市场观察中品种所用的背景颜色 (SetProperty(SName,SYMBOL_TRADE_MODE,SYMBOL_TRADE_MODE_FULL,""))&& class=class="str">"cmt">// 订单执行类型:完全访问权限 (SetProperty(SName,SYMBOL_TRADE_EXEMODE,SYMBOL_TRADE_EXECUTION_INSTANT,""))&& class=class="str">"cmt">// 成交执行模式:即时执行 (SetProperty(SName,SYMBOL_ORDER_GTC_MODE,SYMBOL_ORDERS_GTC,""))&& class=class="str">"cmt">// 止损和止盈订单限期:最佳直至取消 (SetProperty(SName,SYMBOL_FILLING_MODE,SYMBOL_FILLING_FOK,""))&& class=class="str">"cmt">// 订单执行模式:填单或终止 (SetProperty(SName,SYMBOL_EXPIRATION_MODE,SYMBOL_EXPIRATION_GTC,""))&& class=class="str">"cmt">// 订单限期模式:无限定时间,直至明确取消 (SetProperty(SName,SYMBOL_ORDER_MODE,class="num">127,"")) && class=class="str">"cmt">// 订单类型:所有订单类型 (SetProperty(SName,SYMBOL_TRADE_CALC_MODE,SYMBOL_CALC_MODE_FOREX,""))&& class=class="str">"cmt">// 计算合约价值的方法 (SetProperty(SName,SYMBOL_MARGIN_HEDGED_USE_LEG,false,""))&& class=class="str">"cmt">// 使用较大的分支计算对冲保证金 (SetProperty(SName,SYMBOL_SWAP_MODE,SYMBOL_SWAP_MODE_POINTS,""))&& class=class="str">"cmt">// 掉期利率计算模型:以点数为单位计算掉期利率 (SetProperty(SName,SYMBOL_SWAP_ROLLOVER3DAYS,WEDNESDAY,"")) && class=class="str">"cmt">// 掉期日:周三 (SetProperty(SName,SYMBOL_OPTION_MODE,class="num">0,"")) && class=class="str">"cmt">// 期权类型 (SetProperty(SName,SYMBOL_OPTION_RIGHT,class="num">0,"")) && class=class="str">"cmt">// 期权加权 (SetProperty(SName,SYMBOL_TRADE_STOPS_LEVEL,class="num">0,"")) && class=class="str">"cmt">// 设置止损订单与当前收盘价的最小间距 (SetProperty(SName,SYMBOL_TRADE_FREEZE_LEVEL,class="num">0,"")) && class=class="str">"cmt">// 交易操作的冻结间距(以点数为单位)
品种属性初始化的收尾字段
在自定义品种的配置收口阶段,还有一批双精度与日期类属性需要用 SetProperty 写进符号描述里。期货类符号才用得上的起止时间,直接以 0 传参占位即可,现货外汇品种通常忽略这两行也不会报错。 期权执行价、债券应计利息与面值、抵押品种的流动资金率,这些宏在外汇黄金报价里基本是 0 值占位;但 SYMBOL_TRADE_TICK_SIZE 和 SYMBOL_POINT 必须给对,EURUSD 一类标准品种填 0.00001,否则点值计算会整体偏移。 真正影响下单逻辑的是合约规模与最小交易量:SYMBOL_TRADE_CONTRACT_SIZE 设 100000 代表标准手,SYMBOL_VOLUME_MIN 设 0.01 即允许 0.01 手起步。外汇贵金属杠杆高、波动剧烈,参数填错可能在 MT5 里开出非预期手数,实盘前务必用 SymbolInfoInteger / SymbolInfoDouble 回读校验。
(SetProperty(SName,SYMBOL_START_TIME,class="num">0,"")) && class=class="str">"cmt">// 该品种交易开始日期(通常用于期货) (SetProperty(SName,SYMBOL_EXPIRATION_TIME,class="num">0,"")) && class=class="str">"cmt">// 该品种交易结束日期(通常用于期货) class=class="str">"cmt">// 双精度类型属性 (SetProperty(SName,SYMBOL_OPTION_STRIKE,class="num">0,"")) && class=class="str">"cmt">// 期权执行价格 (SetProperty(SName,SYMBOL_SESSION_PRICE_LIMIT_MAX,class="num">0,"")) && class=class="str">"cmt">// 时段的最低允许价格数值 (SetProperty(SName,SYMBOL_SESSION_PRICE_LIMIT_MIN,class="num">0,"")) && class=class="str">"cmt">// 时段的最高允许价格数值 (SetProperty(SName,SYMBOL_SESSION_PRICE_SETTLEMENT,class="num">0,"")) && class=class="str">"cmt">// 当前时段的结算价格 (SetProperty(SName,SYMBOL_TRADE_ACCRUED_INTEREST,class="num">0,"")) && class=class="str">"cmt">// 应计利息(债券) (SetProperty(SName,SYMBOL_TRADE_FACE_VALUE,class="num">0,"")) && class=class="str">"cmt">// 面值(债券) (SetProperty(SName,SYMBOL_TRADE_LIQUIDITY_RATE,class="num">0,"")) && class=class="str">"cmt">// 流动资金率(用于抵押品种) (SetProperty(SName,SYMBOL_TRADE_TICK_SIZE,class="num">0.00001,"")) && class=class="str">"cmt">// 最低价格变化 (SetProperty(SName,SYMBOL_TRADE_TICK_VALUE,class="num">1,"")) && class=class="str">"cmt">// 逐笔报价值 (SetProperty(SName,SYMBOL_TRADE_CONTRACT_SIZE,class="num">100000,"")) && class=class="str">"cmt">// 交易合约规模 (SetProperty(SName,SYMBOL_POINT,class="num">0.00001,"")) && class=class="str">"cmt">// 点数值 (SetProperty(SName,SYMBOL_VOLUME_MIN,class="num">0.01,"")) && class=class="str">"cmt">// 成交执行的最小交易量