对以下自动化交易EA代码进行优化优化成双向交易既可以sell做空也可以buy做多并且满足以下交易的均线条件:1、以15分钟为一个交易周期15分钟周期K线收盘价处于6日均线、15日均线和30日均线之上开始上穿6日均线开始做多当15分钟周期K线收盘价下穿8日均线指令平仓out交易结束;2、以15分钟为一个交易周期15分钟周期K线收盘价开始处于6日均线、15日均线和30日均线之下并且下穿30日均线的时候
以下是优化后的代码:
//+------------------------------------------------------------------+
//| MovingAverageCrossoverEA.mq5 |
//| Created by ChatGPT |
//+------------------------------------------------------------------+
#property copyright "Created by ChatGPT"
#property link "https://www.example.com"
#property version "1.000"
//---
#include <Trade\PositionInfo.mqh>
#include <Trade\Trade.mqh>
#include <Trade\SymbolInfo.mqh>
CPositionInfo m_position; // trade position object
CTrade m_trade; // trading object
CSymbolInfo m_symbol; // symbol info object
//--- input parameters
input double Lots = 0.5; // 交易手数
input int FastMA = 6; // 快速均线周期
input int SlowMA = 27; // 慢速均线周期
input ulong m_magic=42828093; // 魔术数字
ulong m_slippage=10; // 滑点
//---
int handle_fastMA; // 快速均线指标句柄
int handle_slowMA; // 慢速均线指标句柄
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//---
if(!m_symbol.Name(Symbol())) // 设置交易品种名称
return(INIT_FAILED);
RefreshRates();
string err_text="";
if(!CheckVolumeValue(Lots,err_text))
{
Print(err_text);
return(INIT_PARAMETERS_INCORRECT);
}
//---
m_trade.SetExpertMagicNumber(m_magic);
if(IsFillingTypeAllowed(SYMBOL_FILLING_FOK))
m_trade.SetTypeFilling(ORDER_FILLING_FOK);
else if(IsFillingTypeAllowed(SYMBOL_FILLING_IOC))
m_trade.SetTypeFilling(ORDER_FILLING_IOC);
else
m_trade.SetTypeFilling(ORDER_FILLING_RETURN);
m_trade.SetDeviationInPoints(m_slippage);
//--- 创建快速均线指标句柄
handle_fastMA = iMA(m_symbol.Name(), Period(), FastMA, 0, MODE_SMA, PRICE_CLOSE);
//--- 创建慢速均线指标句柄
handle_slowMA = iMA(m_symbol.Name(), Period(), SlowMA, 0, MODE_SMA, PRICE_CLOSE);
//--- 检查指标句柄是否创建成功
if(handle_fastMA == INVALID_HANDLE || handle_slowMA == INVALID_HANDLE)
{
Print("Failed to create moving average indicators for the symbol ", m_symbol.Name());
return(INIT_FAILED);
}
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//---
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
//--- 仅在新K线生成时进行交易
static datetime PrevBars=0;
datetime time_0=iTime(0);
if(time_0==PrevBars)
return;
PrevBars=time_0;
//--- 获取均线值
double fastMA = iMA(m_symbol.Name(), Period(), FastMA, 0, MODE_SMA, PRICE_CLOSE);
double slowMA = iMA(m_symbol.Name(), Period(), SlowMA, 0, MODE_SMA, PRICE_CLOSE);
//--- 检查当前是否有持仓
for(int i=PositionsTotal()-1;i>=0;i--)
{
if(m_position.SelectByIndex(i))
{
if(m_position.Symbol()==m_symbol.Name() && m_position.Magic()==m_magic)
{
if(m_position.PositionType()==POSITION_TYPE_BUY && fastMA < slowMA)
{
//--- 卖出持仓
m_trade.PositionClose(m_position.Ticket());
break;
}
else if(m_position.PositionType()==POSITION_TYPE_SELL && fastMA > slowMA)
{
//--- 买入持仓
m_trade.PositionClose(m_position.Ticket());
break;
}
}
}
}
//--- 如果快速均线上穿慢速均线,进行买入交易
if(fastMA > slowMA)
{
if (m_position.PositionType() != POSITION_TYPE_BUY) {
m_trade.Buy(Lots, m_symbol.Name());
}
}
//--- 如果快速均线下穿慢速均线,进行卖出交易
else if(fastMA < slowMA)
{
if (m_position.PositionType() != POSITION_TYPE_SELL) {
m_trade.Sell(Lots, m_symbol.Name());
}
}
//--- 如果快速均线下穿慢速均线,进行做空交易
if(fastMA < slowMA)
{
if (m_position.PositionType() != POSITION_TYPE_SELL) {
m_trade.Sell(Lots, m_symbol.Name());
}
}
//--- 如果快速均线上穿慢速均线,进行平仓交易
else if(fastMA > slowMA)
{
if (m_position.PositionType() != POSITION_TYPE_BUY) {
m_trade.PositionClose(m_position.Ticket());
}
}
//--- 如果收盘价上穿28日均线,进行平仓交易
if(fastMA > 28)
{
if (m_position.PositionType() != POSITION_TYPE_BUY) {
m_trade.PositionClose(m_position.Ticket());
}
}
//--- 如果收盘价下穿30日均线,进行做空交易
else if(fastMA < slowMA)
{
if (m_position.PositionType() != POSITION_TYPE_SELL) {
m_trade.Sell(Lots, m_symbol.Name());
}
}
}
//+------------------------------------------------------------------+
//| 刷新交易品种行情数据 |
//+------------------------------------------------------------------+
bool RefreshRates(void)
{
//--- 刷新行情数据
if(!m_symbol.RefreshRates())
{
Print("RefreshRates error");
return(false);
}
//--- 保护返回值不为"零"
if(m_symbol.Ask()==0 || m_symbol.Bid()==0)
return(false);
return(true);
}
//+------------------------------------------------------------------+
//| 检查交易手数的正确性 |
//+------------------------------------------------------------------+
bool CheckVolumeValue(double volume, string &error_description)
{
//--- 最小允许交易手数
double min_volume = m_symbol.LotsMin();
if(volume < min_volume)
{
error_description = StringFormat("Volume is less than the minimal allowed SYMBOL_VOLUME_MIN=%.2f", min_volume);
return(false);
}
//--- 最大允许交易手数
double max_volume = m_symbol.LotsMax();
if(volume > max_volume)
{
error_description = StringFormat("Volume is greater than the maximal allowed SYMBOL_VOLUME_MAX=%.2f", max_volume);
return(false);
}
//--- 获取交易手数变动的最小步长
double volume_step = m_symbol.LotsStep();
int ratio = (int)MathRound(volume / volume_step);
if(MathAbs(ratio * volume_step - volume) > 0.0000001)
{
error_description = StringFormat("Volume is not a multiple of the minimal step SYMBOL_VOLUME_STEP=%.2f, the closest correct volume is %.2f",
volume_step,ratio * volume_step);
return(false);
}
error_description = "Correct volume value";
return(true);
}
//+------------------------------------------------------------------+
//| 检查指定的成交模式是否允许 |
//+------------------------------------------------------------------+
bool IsFillingTypeAllowed(int fill_type)
{
int filling = m_symbol.TradeFillFlags();
return((filling & fill_type) == fill_type);
}
//+------------------------------------------------------------------+
//| 获取指定柱子的时间 |
//+------------------------------------------------------------------+
datetime iTime(const int index, string symbol=NULL, ENUM_TIMEFRAMES timeframe=PERIOD_CURRENT)
{
if(symbol == NULL)
symbol = m_symbol.Name();
if(timeframe == 0)
timeframe = Period();
datetime Time[1];
datetime time =
原文地址: https://www.cveoy.top/t/topic/ioUy 著作权归作者所有。请勿转载和采集!