股票量化交易软件:价格速度测量方法

简介

市场研究和分析有多种不同的方法,主要是技术分析和基础分析。在技术分析中,交易者收集、处理和分析与市场有关的数字数据和参数,包括价格、数量等。在基本面分析中,交易者分析直接或间接影响市场的事件和新闻。在分析基础数据时,主要问题是解释一个事件对市场的影响。这种解释可能会受到交易员的意见和期望的影响。相反,技术数据通常不会产生各种解释,然而,在评估技术分析结果时也存在人为因素。
发现问题
说到市场的技术分析,我们赫兹股票量化指的是使用来自不同科学领域的任何评估系统,无论是数学还是物理。数学在技术分析中的必要性是相当明确的,而将各种物理现象应用于市场则更为有趣。因此,在本文中,赫兹股票量化将考虑这样一个众所周知的物理现象,即速度,它是一个单位时间内运动的度量。当我们看外汇和其他图表时,我们不仅可以清楚地看到当前的价格方向,而且可以看到它的速度,特别是在高波动期。任何人都可以直观地分析图表,并确定当前的价格变化是快还是慢。然而,由于人们的认知差异,这种视觉估计仍然具有高度的主观性。
现实生活中的一个简单例子是一个视觉技巧,在这个技巧中,一辆小型车辆似乎以较慢的速度移动,而一辆大型卡车似乎以较高的速度移动。这个问题是通过速度表来解决的,它以数字显示所有的东西,这对任何人来说都是完全相同的。
价格速度测量方法
在考虑各种测量价格速度的方法之前,让赫兹股票量化回想一下速度实际上是什么。
根据维基百科:
物体的速度是物体相对于一个参照系位置变化的速率,是时间的函数。速度是一个物理向量量;定义它需要大小和方向。
赫兹股票量化如何将这个定义应用于外汇?最简单的方法是用一个价格替换一个物体,并设定一个时间,在这个时间内形成一根棒子或一根蜡烛,作为参照系。从价格图的角度来看,如下所示:

编辑
图 1. 在 H1 时间段将价格显示为日式烛形
在这种情况下,简单的速度测量如下所示:
平均速度 = (收盘价格 — 开盘价格) / 小时数
关于价格随时间变化的确切观察和结论如下:

赫兹股票量化定义了价格每小时通过的平均点数。然而,测量只在一根蜡烛的框架内进行,我们无法在此框架内获得总体趋势图。
但是,如果我们将速度从每小时的点转换为每分钟的点、5分钟的点等,赫兹股票量化就可以在这个H1小时内获得更有价值的价格变动数据。
因此,下面两个结论是显而易见的:在较低的时间段上确定速度对于较高的时间段更为方便。当通过测量价格变动来测量当前时间段的平均速度时,我们应该使用几个烛形。
最后,用这种简单的方法测量速度的要点是,它不提供烛形内部价格动态的深入数据,只显示最终的平均结果。例如,如果知道 H1 烛形的平均速度,赫兹股票量化就无法确定最初的价格是高的,到一个小时结束时价格会大幅下降。
为了清楚起见,让我提供一个完美地说明上述结论的例子。图2显示了H1烛形,其每分钟平均速度是使用Average Speed(平均速度)指标计算得出的。这里等于每分钟2.53点。

编辑切换为居中
图 2. 在 EURUSD H1 上计算平均速度
现在让我们来看看M15上的同样的烛形。

编辑切换为居中
图 3. 在 EURUSD M15 上计算平均速度
图3显示,在所选小时的前15分钟(Average speed是 6.93)内,运动非常强烈,随后显著减速。当然,如果赫兹股票量化把平均速度的四个值加起来,每分钟得到相同的2.53点。因此,将蜡烛分解成组件可以让我们发现许多有关其动力学的数据。
将 H1 烛形分成 M1 间隔会产生更多的数据。

编辑切换为居中
图 4. 在 EURUSD M1 上计算平均速度
还有另一种测量方法,用于计算M1时间段内点的移动速度,
它涉及即时(当前)价格速度。一方面,它的值总是尽可能的相关。另一方面,与分时价格变化配合使用的示例指标如下所示:

编辑
图 5. 即时价格速度指标
显然,评估这样一个混乱(尽管相关)的数据,以便随后在外汇交易中使用,是一个相当具有挑战性的任务。
如赫兹股票量化所知,绝大多数指标都是价格或其分析仪的衍生产品,这些是一些与价格速度相关的著名指标:
动量指标衡量一段时间内的价格变化量。极高或较低的动量值表示当前趋势的延续。这意味着与指标的较大偏差表示当前特定方向的高价格速度。
ADX 趋势指标. 平均定向运动指数显示了当前趋势的强度。实际上,它显示当前的平均速度。
基于测量方法制定交易策略
因此,测试各种价格-速度测量的目标分为三大类:
以单位时间内通过点的比率直接测量平均速度。
以通过的点数与分时数之比来测量速度。
使用跟随趋势的和其他指标进行间接速度测量。
交易策略 1要使用平均速度(Average Speed)指标根据测量速度(单位时间内通过的点数)来测试第一种方法,应将显示趋势方向的过滤器添加到测试策略中,因为指示器显示单位时间内的点数,而不管趋势方向。
我决定使用Coordinated ADX and MACD(协调的ADX和MACD,CAM)指标作为这样的过滤器。交易策略看起来是这样的:
参数
描述
使用的指标
平均速度
使用的指标
Coordinated ADX and MACD (CAM)
时间框架
任意
买入条件
烛形为绿色,而平均速度值高于阈值(参数中预先设置)。
卖出条件
烛形颜色为红色,而平均速度值高于阈值(参数中预先设置)。
退场条件
获利/止损
图 6 显示了买入和卖出的建立

编辑
图 6. 交易策略的入场条件
策略是按照下面的方法实现的:
//+------------------------------------------------------------------+ //| EA 的输入参数 | //+------------------------------------------------------------------+ input string InpEaComment = "Strategy #1"; // EA Comment input int InpMagicNum = 1111; // Magic number input double InpLot = 0.1; // Lots input uint InpStopLoss = 400; // StopLoss in points input uint InpTakeProfit = 500; // TakeProfit in points input uint InpSlippage = 0; // Slippage in points input ENUM_TIMEFRAMES InpInd_Timeframe = PERIOD_H1; // Timeframe for the calculation //--- 平均速度指标的参数 input int InpBars = 1; // Days input ENUM_APPLIED_PRICE InpPrice = PRICE_CLOSE; // Applied price input double InpTrendLev = 2; // Trend Level //--- CAM 指标参数 input uint InpPeriodADX = 10; // ADX period input uint InpPeriodFast = 12; // MACD Fast EMA period input uint InpPeriodSlow = 26; // MACD Slow EMA period //--- CEngine engine; CTrade trade; //--- 声明指标变量和句柄 double lot; ulong magic_number; uint stoploss; uint takeprofit; uint slippage; int InpInd_Handle1,InpInd_Handle2; double avr_speed[],cam_up[],cam_dn[]; //+------------------------------------------------------------------+ //| EA 交易初始化函数 | //+------------------------------------------------------------------+ int OnInit() { //--- 初始化检查 if(!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED)) { Print(InpEaComment,": 不允许进行交易!"); return(INIT_FAILED); } if(!TerminalInfoInteger(TERMINAL_CONNECTED)) { Print(InpEaComment,": 没有连接!"); return(INIT_FAILED); } //--- 取得 Average Speed 指标句柄 InpInd_Handle1=iCustom(Symbol(),InpInd_Timeframe,"Speed Price\\average_speed", InpBars, InpPrice ); if(InpInd_Handle1==INVALID_HANDLE) { Print(InpEaComment,": 获取 average_speed 句柄失败"); Print("Handle = ",InpInd_Handle1," error = ",GetLastError()); return(INIT_FAILED); } //--- 取得 CAM 指标句柄 InpInd_Handle2=iCustom(Symbol(),InpInd_Timeframe,"Speed Price\\CAM", InpPeriodADX, InpPeriodFast, InpPeriodSlow ); if(InpInd_Handle2==INVALID_HANDLE) { Print(InpEaComment,": 获取 average_speed 句柄失败"); Print("Handle = ",InpInd_Handle2," error = ",GetLastError()); return(INIT_FAILED); } //--- ArrayInitialize(avr_speed,0.0); ArrayInitialize(cam_up,0.0); ArrayInitialize(cam_dn,0.0); ArraySetAsSeries(avr_speed,true); ArraySetAsSeries(cam_up,true); ArraySetAsSeries(cam_dn,true); //--- 设置交易参数 lot=NormalizeLot(Symbol(),fmax(InpLot,MinimumLots(Symbol()))); magic_number=InpMagicNum; stoploss=InpStopLoss; takeprofit=InpTakeProfit; slippage=InpSlippage; //--- trade.SetDeviationInPoints(slippage); trade.SetExpertMagicNumber(magic_number); trade.SetTypeFillingBySymbol(Symbol()); trade.SetMarginMode(); trade.LogLevel(LOG_LEVEL_NO); //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| 计时器函数 | //+------------------------------------------------------------------+ void OnTimer() { if(!MQLInfoInteger(MQL_TESTER)) engine.OnTimer(); } //+------------------------------------------------------------------+ //| EA交易分时函数 | //+------------------------------------------------------------------+ void OnTick() { //--- 如果在测试器中工作 if(MQLInfoInteger(MQL_TESTER)) engine.OnTimer(); if(!IsOpenedByMagic(InpMagicNum)) { //--- 取得计算数据 if(!GetIndValue()) return; //--- if(BuySignal()) { //--- 取得相对止损水平的正确止损和获利价格 double sl=CorrectStopLoss(Symbol(),ORDER_TYPE_BUY,0,stoploss); double tp=CorrectTakeProfit(Symbol(),ORDER_TYPE_BUY,0,takeprofit); //--- 开启买入仓位 trade.Buy(lot,Symbol(),0,sl,tp); } else if(SellSignal()) { //--- 取得相对止损水平的正确止损和获利价格 double sl=CorrectStopLoss(Symbol(),ORDER_TYPE_SELL,0,stoploss); double tp=CorrectTakeProfit(Symbol(),ORDER_TYPE_SELL,0,takeprofit); //--- 开启卖出仓位 trade.Sell(lot,Symbol(),0,sl,tp); } } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool BuySignal() { return(avr_speed[0]>=InpTrendLev && cam_up[0]!=EMPTY_VALUE)?true:false; } //+------------------------------------------------------------------+ bool SellSignal() { return(avr_speed[0]>=InpTrendLev && cam_dn[0]!=EMPTY_VALUE)?true:false; } //+------------------------------------------------------------------+ //| 取得当前指标值 | //+------------------------------------------------------------------+ bool GetIndValue() { return(CopyBuffer(InpInd_Handle2,0,0,1,cam_up)<1 || CopyBuffer(InpInd_Handle2,1,0,1,cam_dn)<1 || CopyBuffer(InpInd_Handle1,0,0,1,avr_speed)<1 )?false:true; } //+------------------------------------------------------------------+ //| 使用幻数检查开启的仓位 | //+------------------------------------------------------------------+ bool IsOpenedByMagic(int MagicNumber) { int pos=0; uint total=PositionsTotal(); //--- for(uint i=0; i<total; i++) { if(SelectByIndex(i)) if(PositionGetInteger(POSITION_MAGIC)==MagicNumber) pos++; } return((pos>0)?true:false); } //+------------------------------------------------------------------+ //| 根据索引选择仓位 | //+------------------------------------------------------------------+ bool SelectByIndex(const int index) { ENUM_ACCOUNT_MARGIN_MODE margin_mode=(ENUM_ACCOUNT_MARGIN_MODE)AccountInfoInteger(ACCOUNT_MARGIN_MODE); //--- if(margin_mode==ACCOUNT_MARGIN_MODE_RETAIL_HEDGING) { ulong ticket=PositionGetTicket(index); if(ticket==0) return(false); } else { string name=PositionGetSymbol(index); if(name=="") return(false); } //--- return(true); } //+------------------------------------------------------------------+