期货量化交易软件:Heiken-Ashi指标和移动平均指标组合

这是在 EURUSD 30分钟时段图表上从2022年1月1日到2023年7月5日的运行结果。如果进行优化以及使用其它时段图表应该会有更好的结果。如果在所有交易品种上使用它,应该做优化和测试。

添加图片注释,不超过 140 字(可选)

添加图片注释,不超过 140 字(可选)

代码

添加图片注释,不超过 140 字(可选)

 
 

int OnInit() { //--- handle_iCustomMA=iCustom(_Symbol,my_timeframe,"\\folder/s where you have the indicator\\sma",MAPeriod,MAShift); handle_iCustomHeiken=iCustom(_Symbol,my_timeframe_Heiken,"\\folder/s where you have the indicator\\Heiken_Ashi_copy"); //--- if(handle_iCustomMA==INVALID_HANDLE) { //--- tell about the failure and output the error code PrintFormat("Failed to create handle of the iCustom indicator for the symbol %s/%s, error code %d", _Symbol, EnumToString(my_timeframe), GetLastError()); //--- the indicator is stopped early return(INIT_FAILED); } if(handle_iCustomHeiken==INVALID_HANDLE) { //--- tell about the failure and output the error code PrintFormat("Failed to create handle of the iCustom indicator for the symbol %s/%s, error code %d", _Symbol, EnumToString(my_timeframe_Heiken), GetLastError()); //--- the indicator is stopped early return(INIT_FAILED); } return(INIT_SUCCEEDED); }

此代码用于初始化MQL5语言中的两个自定义指标。第一个指标是使用MAPeriod和MAShift为参数的简单移动平均(Simple Moving Average, SMA),第二个指标是 Heiken Ashi。代码创建每个指标的句柄并且检查错误,如果发现错误,代码就打印错误编号并返回 INIT_FAILED 的值,如果没有发现错误,代码就返回 INIT_SUCCEEDED 的值。

 
 

void OnTick() { double heikenAshiOpen[], heikenAshiHigh[], heikenAshiLow[], heikenAshiClose[]; CopyBuffer(handle_iCustomHeiken,0,0,2,heikenAshiOpen); CopyBuffer(handle_iCustomHeiken,1,0,2,heikenAshiHigh); CopyBuffer(handle_iCustomHeiken,2,0,2,heikenAshiLow); CopyBuffer(handle_iCustomHeiken,3,0,2,heikenAshiClose); Comment("heikenAshiOpen ",DoubleToString(heikenAshiOpen[0],_Digits), "\n heikenAshiHigh ",DoubleToString(heikenAshiHigh[0],_Digits), "\n heikenAshiLow ",DoubleToString(heikenAshiLow[0],_Digits), "\n heikenAshiClose ",DoubleToString(heikenAshiClose[0],_Digits)); //--- MqlTick tick; double last_price = tick.ask; SymbolInfoTick(_Symbol,tick); int total = PositionsTotal(); //--- // Retrieve the current value MqlTradeResult result; MqlRates rates[]; //--- double array_ma[]; ArraySetAsSeries(array_ma,true); int start_pos2=0,count2=5; if(!iGetArray2(handle_iCustomMA,0,start_pos2,count2,array_ma)) return; //------------------------------------------------------------------------------ { if(DoubleToString(heikenAshiClose[0],_Digits) < DoubleToString(heikenAshiOpen[0],_Digits) && (DoubleToString(heikenAshiClose[1],_Digits) > DoubleToString(heikenAshiOpen[1],_Digits))) { Print("Open Order Buy"); Alert(" Buying"); Orden="Buy"; sl=NormalizeDouble(tick.ask - ptsl*_Point,_Digits); tp=NormalizeDouble(tick.bid + pttp*_Point,_Digits); trade.PositionOpen(_Symbol,ORDER_TYPE_BUY,get_lot(tick.bid),tick.bid,sl,tp,"Buy"); return; } } { if(DoubleToString(heikenAshiClose[0],_Digits) > DoubleToString(heikenAshiOpen[0],_Digits) && (DoubleToString(heikenAshiClose[1],_Digits) < DoubleToString(heikenAshiOpen[1],_Digits))) { Print("Open Order Sell"); Alert(" Selling"); Orden="Sell"; sl=NormalizeDouble(tick.bid + ptsl*_Point,_Digits); tp=NormalizeDouble(tick.ask - pttp*_Point,_Digits); trade.PositionOpen(_Symbol,ORDER_TYPE_SELL,get_lot(tick.ask),tick.ask,sl,tp,"Sell"); return; } } if(total>0) { if(Orden=="Sell" &&(DoubleToString(heikenAshiClose[0],_Digits) < DoubleToString(heikenAshiOpen[0],_Digits) )) { trade.PositionClose(_Symbol,5); Print("cerró sell"); return; } if(Orden=="Buy" &&(DoubleToString(heikenAshiClose[0],_Digits) > DoubleToString(heikenAshiOpen[0],_Digits) )) { trade.PositionClose(_Symbol,5); Print("cerró buy"); return; } } }

这段代码是一个MQL5脚本,用于在期货市场中打开和关闭头寸。它首先声明四个double型数组(heikenAshiOpen、heikenAshiHigh、heikenAshiLow和heikenAshiClose),并从自定义指标“iCustomHeiken”中复制数值。然后,它从交易品种中取得当前的分时数据,并声明MqlTradeResult和MqlRates数组。然后,它为移动平均值声明一个数组(array_ma),并将该数组设置为一个序列。然后,它从自定义指标“iCustomMA”中读取数值,并将它们存储在array_ma数组中。最后,它检查当前 Heiken-Ashi 的收盘价是否低于开盘价,以及上一个 Heiken-Ashi 开盘价是否高于开盘价,如果是,它将打开一个具有指定止损和获利的买入订单。它还检查当前 Heiken-Ashi 收盘价是否高于开盘价,以及上一次 Heiken-Ashi 开盘价是否低于开盘价,如果是,它将打开一个具有指定止损和获利的卖出订单。如果有任何持仓,它会检查 Heiken-Ashi 的收盘价是否低于卖出订单的开盘价,高于买入订单的收盘价,如果是,它会平仓。

为了阐释清楚,CopyBuffer的第二个int是开始计数的位置的值,第三个是计数数量的值。我用的是2,而不是1,来处理1-n(在这种情况下,就是紧靠前方的Heiken Ashi烛形)。这已经在strat中用于查看if条件下的颜色变化,以打开或不打开订单。

打开或关闭订单的两个条件是您应该在代码中修改的条件,例如,您可以在打开订单之前使用更多相同颜色的烛形,或者跳到不同颜色的第二个烛形来关闭订单。

为了关闭订单,另一个好的解决方案是另一个具有不同周期数的SMA,并使用交叉信号来关闭订单,如图中所示:

添加图片注释,不超过 140 字(可选)

 
 

//+------------------------------------------------------------------+ double get_lot(double price) { if(inp_lot_type==LOT_TYPE_FIX) return(normalize_lot(inp_lot_fix)); double one_lot_margin; if(!OrderCalcMargin(ORDER_TYPE_BUY,_Symbol,1.0,price,one_lot_margin)) return(inp_lot_fix); return(normalize_lot((AccountInfoDouble(ACCOUNT_BALANCE)*(inp_lot_risk/100))/ one_lot_margin)); } double normalize_lot(double lt) { double lot_step = SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_STEP); lt = MathFloor(lt / lot_step) * lot_step; double lot_minimum = SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN); lt = MathMax(lt, lot_minimum); return(lt); } bool iGetArray2(const int handle2,const int buffer2,const int start_pos2, const int count2,double &arr_buffer2[]) { bool result2=true; if(!ArrayIsDynamic(arr_buffer2)) { //if(InpPrintLog) PrintFormat("ERROR! EA: %s, FUNCTION: %s, this a no dynamic array!",__FILE__,__FUNCTION__); return(false); } ArrayFree(arr_buffer2); //--- reset error code ResetLastError(); //--- fill a part of the iBands array with values from the indicator buffer int copied2=CopyBuffer(handle2,buffer2,start_pos2,count2,arr_buffer2); if(copied2!=count2) { //--- if the copying fails, tell the error code //if(InpPrintLog) PrintFormat("ERROR! EA: %s, FUNCTION: %s, amount to copy: %d, copied: %d, error code %d", __FILE__,__FUNCTION__,count2,copied2,GetLastError()); //--- quit with zero result - it means that the indicator is considered as not calculated return(false); } return(result2); }

  • 23
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值