欢迎光临散文网 会员登陆 & 注册

量化交易软件:迷你行情模拟器或手动策略测试器

2023-07-19 16:05 作者:bili_45793681098  | 我要投稿

引言

金融交易始于理论基础的研究: 收益策略, 数据分析方法, 成功的交易模型。所有新入行交易者都有相同的想法 — 每个人都想赚钱。但是每个人都定义了自己的优先级, 条件, 机会, 目标等。

编辑切换为居中

新入行交易者的行为有若干种情况。

  • "一次全部" 选项" 大多数初学者都想快速赚取很多钱。他们迷信于一个诱惑广告: 用很少的钱, 甚至免费即可得到神奇而无暇的策略。所有这一切看起来即快捷又容易, 但是, 损失本钱也同样迅速和轻易。

  • "教育, 教育再教育" 选项: 负责任的新手培训, 是要他们不能相信童话故事。他们需要深入研究行情和交易系统的规律。那就是当在真实账户里开始交易后 — 事实证明利润会低于依据教科书的预期。这是如何发生的, 接下来应如何做?

一旦出现第一种状况, 大多数新人会对金融市场永远失望。而新人从第二种情景中继续研究理论及其实际策略。

本文主要针对那些迫不及待地想要在模拟账户上进行交易并测试其策略的初学者。这里也有两个选项:

  • 一组想要尝试研究一个短线策略。但如果其成员为全职工作, 他们只能在夜间休息, 因为市场在周末才会闭市。

  • 第二类交易者使用中线或长线策略。他们绝对不想花一整年时间在模拟账户上完善自己的策略。

自然而然地, 您也许会想: 如果有一个历史图表能够快速而有效地测试任何策略, 那这些还会如此困难吗?然而, 在实践中, 它并不能总是奏效: 出于某种原因, 经常会发生在回测时有出色表现的策略却在 "真实" 行情中效果很差。无论如何, 最好在更接近现实的系统中学习交易。举例来说, 行情模拟器恰好足够 (这样的程序可以在互联网上购得)。

在这篇文章中, 我想讨论一下我自己在赫兹量化中实现的这样一个系统。与完整的终端版本相比, 我所编写的 "迷你行情模拟器" 指标功能有限。它设计用于策略的理论验证。

应用程序功能

应用程序有自己的控制面板, 以及 "父系统" 的按钮, 即赫兹量化终端本身。

这是模拟器可以执行的 主要动作。

  1. 只能放置两个不同方向的订单: 买入和卖出。在设置订单和交易量之前, 还支持止损和止盈的设置。一旦订单被放置, 它可以被修改, 并且可以拖动其停止价位。

  2. 只有七种建模速度, 它们可以划分为三组。第一个是 "珠宝", 它所涉及的建模基于来自分钟时间帧的分笔报价, 就像在策略测试器中一样。第二个考虑分钟数据, 构建时无需生成 (这种模式更快, 但不太精准)。第三种模式是最快的: 每秒一根蜡烛, 无论时间帧如何。

  3. 所提供的当前交易信息: 利润, 点数和交易量。给出的数据针对当前和过去的订单, 以及自仿真开始时的正常交易。

  4. 终端中的所有标准图形对象都可用。

  5. 支持所有的标准时间帧 (通过终端面板的按钮切换)。


编辑切换为居中

图例. 1. 应用程序的控件和外观


分笔报价生成系统

分笔报价的生成原理来自文章 "赫兹量化终端策略测试器中的分笔报价生成算法"。它已被创造性地修改并作为替代版本呈现。

两个函数负责生成分笔报价 — 主要和辅助。

主函数是Tick Generation。它传递了两个参数: 蜡烛本身和响应数据 (ticks) 的数组。之后, 如果输入蜡烛的所有四个价位彼此相等, 则 ticks 的交易量设置为等于一个分笔报价。这样做是为了消除所传递数据不正确的情况下可能发生的除零错误。

随后会形成一根新的蜡烛。如果蜡烛内有 1 至 3 个分笔报价, 则按上文所述的分笔报价生成过程继续。

如果有 3 个以上的分笔报价, 则操作变得更加复杂。所传递的蜡烛被分成三个不等份 (在下面的代码中提供了划分的原则, 分别为 看跌 和 看涨 蜡烛。然后, 如果顶部和底部不再有分笔报价, 则进行调整。接下来, 根据蜡烛的性质将控制权转交给辅助函数。

//+------------------------------------------------------------------+ //| Tick Generation 函数                                              | //+------------------------------------------------------------------+ void func_tick_generation( MqlRates &rates,      // 蜡烛数据 double &tick[]        // 分笔报价数组 ) { if(rates.open==rates.close && rates.high==rates.low && rates.open==rates.high){rates.tick_volume=1;} if(rates.tick_volume<4)// 少于四个分笔报价 { ArrayResize(tick,int(rates.tick_volume));         // 调整分笔报价数组大小 if(rates.tick_volume==1)tick[0]=rates.close;      // 一个分笔报价 if(rates.tick_volume==2)                          // 两个分笔报价 { tick[0]=rates.open; tick[1]=rates.close; } if(rates.tick_volume==3)                          // 三个分笔报价 { tick[0]=rates.open; tick[2]=rates.close; if(rates.open==rates.close)                      // 朝着一个方向前进, 并回到了开盘价 { if(rates.high==rates.open)tick[1]=rates.low; if(rates.low==rates.open)tick[1]=rates.high; } if(rates.close==rates.low && rates.open!=rates.high)tick[1]=rates.high;           // 朝着一个方向前进, 回滚并突破开盘价 if(rates.close==rates.high && rates.open!=rates.low)tick[1]=rates.low; if(rates.open==rates.high && rates.close!=rates.low)tick[1]=rates.low;            // 朝着一个方向前进, 回滚但未突破开盘价 if(rates.open==rates.low && rates.close!=rates.high)tick[1]=rates.high; if((rates.open==rates.low && rates.close==rates.high) || (rates.open==rates.high && rates.close==rates.low)) { tick[1]=NormalizeDouble((((rates.high-rates.low)/2)+rates.low),_Digits);           // 在一个方向的若干点数 } } } if(rates.tick_volume>3)      // 超过三个分笔报价 { // 按照点数计算蜡烛的大小 int candle_up=0; int candle_down=0; int candle_centre=0; if(rates.open>rates.close) { candle_up=int(MathRound((rates.high-rates.open)/_Point)); candle_down=int(MathRound((rates.close-rates.low)/_Point)); } if(rates.open<=rates.close) { candle_up=int(MathRound((rates.high-rates.close)/_Point)); candle_down=int(MathRound((rates.open-rates.low)/_Point)); } candle_centre=int(MathRound((rates.high-rates.low)/_Point)); int candle_all=candle_up+candle_down+candle_centre;      // 走势的总长度 int point_max=int(MathRound(double(candle_all)/2));      // 分笔报价的最大可能数量 double share_up=double(candle_up)/double(candle_all); double share_down=double(candle_down)/double(candle_all); double share_centre=double(candle_centre)/double(candle_all); // 计算每个部分的参考点数量 char point=0; if(rates.tick_volume<10)point=char(rates.tick_volume); else point=10; if(point>point_max)point=char(point_max); char point_up=char(MathRound(point*share_up)); char point_down=char(MathRound(point*share_down)); char point_centre=char(MathRound(point*share_centre)); // 检查所选范围的参考点 if(candle_up>0 && point_up==0) {point_up=1;point_centre=point_centre-1;} if(candle_down>0 && point_down==0) {point_down=1;point_centre=point_centre-1;} // 调整输出数组的大小 ArrayResize(tick,11); char p=0;                     // 分笔报价数组的索引 (tick[]) tick[p]=rates.open;           // 第一个分笔报价等于开盘价 if(rates.open>rates.close)    // 下行趋势 { func_tick_small(rates.high,1,candle_up,point_up,tick,p); func_tick_small(rates.low,-1,candle_centre,point_centre,tick,p); func_tick_small(rates.close,1,candle_down,point_down,tick,p); ArrayResize(tick,p+1); } if(rates.open<=rates.close)   // 上行或十字星 { func_tick_small(rates.low,-1,candle_down,point_down,tick,p); func_tick_small(rates.high,1,candle_centre,point_centre,tick,p); func_tick_small(rates.close,-1,candle_up,point_up,tick,p); ArrayResize(tick,p+1); } } }

顾名思义, 赫兹量化Tick Small 函数执行次级分笔报价。它接收有关上次处理的订单信息, 走势 (上或下) 的方向, 所需的步数, 最后价格, 并将计算的步数传递给上述的分笔报价数组。结果数组包含的分笔报价不超过 11 个。


量化交易软件:迷你行情模拟器或手动策略测试器的评论 (共 条)

分享到微博请遵守国家法律