一、调用多指标多周期EA示例
shuju.mqh:
class shuju
{
public:
shuju()
{
}
~shuju()
{
}
void MA(
double &ma[],
int count,
string symbol, // 交易品种名称
ENUM_TIMEFRAMES period, // 周期
int ma_period, // 平均周期
int ma_shift, // 平移
ENUM_MA_METHOD ma_method, // 平滑类型
ENUM_APPLIED_PRICE applied_price // 价格或者处理程序类型
);
void Bands(
double &Upper[],
double &Lower[],
double &Middle[],
int count,
string symbol, // 交易品种名称
ENUM_TIMEFRAMES period, // 周期
int bands_period, // 平均线计算周期
int bands_shift, // 指标平移
double deviation, // 标准差数
ENUM_APPLIED_PRICE applied_price // 价格或处理器类型
);
void Stochastic(
double &data0[],
double &data1[],
int count,
string symbol, // 交易品种名称
ENUM_TIMEFRAMES period, // 周期
int Kperiod, // K线周期 (用于计算的柱数)
int Dperiod, // D线周期 (开始平滑周期)
int slowing, // 最终平滑
ENUM_MA_METHOD ma_method, // 平滑类型
ENUM_STO_PRICE price_field // 随机计算法
);
int getrates(MqlRates &rates[],int count,string symbol,ENUM_TIMEFRAMES tf);
};
void shuju::MA(
double &ma[],
int count, // 复制总数
string symbol, // 交易品种名称
ENUM_TIMEFRAMES period, // 周期
int ma_period, // 平均周期
int ma_shift, // 平移
ENUM_MA_METHOD ma_method, // 平滑类型
ENUM_APPLIED_PRICE applied_price // 价格或者处理程序类型
){
int ma_h = iMA(symbol,period,ma_period,ma_shift,ma_method,applied_price);
ArraySetAsSeries(ma,true);
CopyBuffer(ma_h,0,0,count,ma);
IndicatorRelease(ma_h);
}
void shuju::Bands(
double &Upper[],
double &Lower[],
double &Middle[],
int count,
string symbol, // 交易品种名称
ENUM_TIMEFRAMES period, // 周期
int bands_period, // 平均线计算周期
int bands_shift, // 指标平移
double deviation, // 标准差数
ENUM_APPLIED_PRICE applied_price // 价格或处理器类型
){
int h = iBands(symbol,period,bands_period,bands_shift,deviation,applied_price);
ArraySetAsSeries(Upper, true);
ArraySetAsSeries(Lower, true);
ArraySetAsSeries(Middle, true);
CopyBuffer(h,0,0,count,Middle);
CopyBuffer(h,1,0,count,Upper);
CopyBuffer(h,2,0,count,Lower);
IndicatorRelease(h);
}
void shuju::Stochastic(
double &data0[],
double &data1[],
int count,
string symbol, // 交易品种名称
ENUM_TIMEFRAMES period, // 周期
int Kperiod, // K线周期 (用于计算的柱数)
int Dperiod, // D线周期 (开始平滑周期)
int slowing, // 最终平滑
ENUM_MA_METHOD ma_method, // 平滑类型
ENUM_STO_PRICE price_field // 随机计算法
){
int h = iStochastic(symbol,period,Kperiod,Dperiod,slowing,ma_method,price_field);
ArraySetAsSeries(data0, true);
ArraySetAsSeries(data1, true);
CopyBuffer(h,0,0,count,data0);
CopyBuffer(h,1,0,count,data1);
IndicatorRelease(h);
}
int shuju::getrates(MqlRates &rates[],int count,string symbol,ENUM_TIMEFRAMES tf)
{
ArraySetAsSeries(rates, true);
return(CopyRates(symbol,tf,0,count,rates));
}
jiaoyi.mqh:
class jiaoyi
{
public:
ulong buy(string symbol,double lots,int slpoint,int tppoint,string com,int magic);
ulong buyplus(string symbol,double lots,int slpoint,int tppoint,string com,int magic);
ulong sell(string symbol,double lots,int slpoint,int tppoint,string com,int magic);
ulong sellplus(string symbol,double lots,int slpoint,int tppoint,string com,int magic);
void closeallbuy(string symbol);
void closeallsell(string symbol);
};
ulong jiaoyi::buy(string symbol,double lots,int slpoint,int tppoint,string com,int magic)
{
MqlTradeRequest request = {};
MqlTradeResult result = {};
request.action = TRADE_ACTION_DEAL;
request.symbol = symbol;
request.type = ORDER_TYPE_BUY;
request.volume = lots;
request.deviation = 100;
request.type_filling = ORDER_FILLING_IOC;
request.price = SymbolInfoDouble(symbol,SYMBOL_ASK);
// SYMBOL_TRADE_STOPS_LEVEL 设置止损/止盈时,与当前价格的最小距离限制(以点为单位)
if(slpoint>SymbolInfoInteger(symbol,SYMBOL_TRADE_STOPS_LEVEL))
{
request.sl = SymbolInfoDouble(symbol,SYMBOL_ASK) - slpoint*SymbolInfoDouble(symbol,SYMBOL_POINT);
}
if(tppoint>SymbolInfoInteger(symbol,SYMBOL_TRADE_STOPS_LEVEL))
{
request.tp = SymbolInfoDouble(symbol,SYMBOL_ASK) + tppoint*SymbolInfoDouble(symbol,SYMBOL_POINT);
}
request.comment = com;
request.magic = magic;
// --- 发送请求
if(!OrderSend(request, result))
PrintFormat("OrderSend error %d", GetLastError()); // 如果不能发送请求,输出错误代码
// --- 显示操作信息
PrintFormat("retcode=%u deal=%I64u order=%I64u",result.retcode,result.deal,result.order);
return(result.order);
}
ulong jiaoyi::buyplus(string symbol,double lots,int slpoint,int tppoint,string com,int magic)
{
ulong ticket = 0;
int total = PositionsTotal();
for(int i=total-1; i>=0; i--)
{
if(PositionGetTicket(i)>0)
{
if(PositionGetString(POSITION_SYMBOL)==symbol && PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY && PositionGetInteger(POSITION_MAGIC)==magic && PositionGetString(POSITION_COMMENT)==com)
return(0);
}
}
ticket = buy(symbol,lots,slpoint,tppoint,com,magic);
return(ticket);
}
ulong jiaoyi::sell(string symbol,double lots,int slpoint,int tppoint,string com,int magic)
{
MqlTradeRequest request = {};
MqlTradeResult result = {};
request.action = TRADE_ACTION_DEAL;
request.symbol = symbol;
request.type = ORDER_TYPE_SELL;
request.volume = lots;
request.deviation = 100;
request.type_filling = ORDER_FILLING_IOC;
request.price = SymbolInfoDouble(symbol,SYMBOL_BID);
if(slpoint>SymbolInfoInteger(symbol,SYMBOL_TRADE_STOPS_LEVEL))
{
request.sl = SymbolInfoDouble(symbol,SYMBOL_BID) + slpoint*SymbolInfoDouble(symbol,SYMBOL_POINT);
}
if(tppoint>SymbolInfoInteger(symbol,SYMBOL_TRADE_STOPS_LEVEL))
{
request.tp = SymbolInfoDouble(symbol,SYMBOL_BID) - tppoint*SymbolInfoDouble(symbol,SYMBOL_POINT);
}
request.comment = com;
request.magic = magic;
// --- 发送请求
if(!OrderSend(request, result))
PrintFormat("OrderSend error %d", GetLastError());
// --- 显示操作信息
PrintFormat("retcode=%u deal=%I64u order=%I64u",result.retcode,result.deal,result.order);
return(result.order);
}
ulong jiaoyi::sellplus(string symbol,double lots,int slpoint,int tppoint,string com,int magic)
{
ulong ticket = 0;
int total = PositionsTotal();
for(int i=total-1; i>=0; i--)
{
if(PositionGetTicket(i)>0)
{
if(PositionGetString(POSITION_SYMBOL)==symbol && PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_SELL && PositionGetInteger(POSITION_MAGIC)==magic && PositionGetString(POSITION_COMMENT)==com)
return(0);
}
}
ticket = sell(symbol,lots,slpoint,tppoint,com,magic);
return(ticket);
}
void jiaoyi::closeallbuy(string symbol)
{
int total = PositionsTotal();
for(int i=total-1; i>=0; i--)
{
ulong ticket = PositionGetTicket(i);
if(ticket>0)
{
if(PositionGetString(POSITION_SYMBOL)==symbol && PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY)
{
MqlTradeRequest request = {};
MqlTradeResult result = {};
request.action = TRADE_ACTION_DEAL; // 交易操作类型
request.symbol = symbol; // 交易品种
request.volume = PositionGetDouble(POSITION_VOLUME); // 交易量
request.type = ORDER_TYPE_SELL; // 订单类型
request.price = SymbolInfoDouble(symbol,SYMBOL_BID); // 持仓价格
request.deviation= 100; // 允许价格偏差
request.type_filling=ORDER_FILLING_IOC;
request.position = ticket;
if(!OrderSend(request,result))
PrintFormat("OrderSend error %d",GetLastError());
}
}
}
}
void jiaoyi::closeallsell(string symbol)
{
int total = PositionsTotal();
for(int i=total-1; i>=0; i--)
{
ulong ticket = PositionGetTicket(i);
if(ticket>0)
{
if(PositionGetString(POSITION_SYMBOL)==symbol && PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_SELL)
{
MqlTradeRequest request = {};
MqlTradeResult result = {};
request.action = TRADE_ACTION_DEAL; // 交易操作类型
request.symbol = symbol; // 交易品种
request.volume = PositionGetDouble(POSITION_VOLUME); // 交易量
request.type = ORDER_TYPE_BUY; // 订单类型
request.price = SymbolInfoDouble(symbol,SYMBOL_ASK); // 持仓价格
request.deviation= 100; // 允许价格偏差
request.type_filling=ORDER_FILLING_IOC;
request.position = ticket;
if(!OrderSend(request,result))
PrintFormat("OrderSend error %d",GetLastError());
}
}
}
}
EA:
#include <myClass/jiaoyi.mqh>
#include <myClass/shuju.mqh>
jiaoyi jy;
shuju sj;
input double LOTS = 0.01; // 开仓手数
input int sl_point = 700; // 止损点数
input int tp_point = 700; // 止盈点数
input int MAGIC = 12345; // 幻数
input int little_period = 5; // 小均线周期
input int large_period = 10; // 大均线周期
input int bollinger_period = 20; // 布林带周期
input double bollinger_deviation = 2; // 布林带偏差
input int InpKPeriod = 5; // K period
input int InpDPeriod = 3; // D period
input int InpSlowing = 3; // Slowing
int OnInit()
{
return(INIT_SUCCEEDED);
}
void OnDeinit(const int reason)
{
}
void OnTick()
{
double m30_ma_xiao[]; // 30分钟小周期MA
sj.MA(m30_ma_xiao,4,Symbol(),PERIOD_M30,little_period,0,MODE_SMA,PRICE_CLOSE);
double m30_ma_da[]; // 30分钟大周期MA
sj.MA(m30_ma_da,4,Symbol(),PERIOD_M30,large_period,0,MODE_SMA,PRICE_CLOSE);
double h4_ma_xiao[]; // H4小周期MA
sj.MA(h4_ma_xiao,4,Symbol(),PERIOD_H4,little_period,0,MODE_SMA,PRICE_CLOSE);
double h4_ma_da[]; // H4大周期MA
sj.MA(h4_ma_da,4,Symbol(),PERIOD_H4,large_period,0,MODE_SMA,PRICE_CLOSE);
double m30_bands_up[], m30_bands_low[], m30_bands_mid[];
sj.Bands(m30_bands_up,m30_bands_low,m30_bands_mid,4,Symbol(),PERIOD_M30,bollinger_period,0,bollinger_deviation,PRICE_CLOSE);
double h4_bands_up[], h4_bands_low[], h4_bands_mid[];
sj.Bands(h4_bands_up,h4_bands_low,h4_bands_mid,4,Symbol(),PERIOD_H4,bollinger_period,0,bollinger_deviation,PRICE_CLOSE);
double m30_k[], m30_d[];
sj.Stochastic(m30_k,m30_d,4,Symbol(),PERIOD_M30,InpKPeriod,InpDPeriod,InpSlowing,MODE_SMA,STO_LOWHIGH);
double h4_k[], h4_d[];
sj.Stochastic(h4_k,h4_d,4,Symbol(),PERIOD_H4,InpKPeriod,InpDPeriod,InpSlowing,MODE_SMA,STO_LOWHIGH);
MqlRates m30_rate[];
sj.getrates(m30_rate,4,Symbol(),PERIOD_M30);
MqlRates h4_rate[];
sj.getrates(h4_rate,4,Symbol(),PERIOD_H4);
// 开多单:H4K线下穿布林带下轨,且M30小周期均线在大周期均线之上,且M30指标KDJ金叉
if(h4_rate[0].low<h4_bands_low[0] && m30_ma_xiao[0]>m30_ma_da[0] && m30_k[1]>m30_d[1] && m30_k[2]<m30_d[2])
jy.buyplus(Symbol(),LOTS,sl_point,tp_point,"buy",MAGIC);
// 平仓多单:在M30指标KDJ死叉
if(m30_k[1]<m30_d[1] && m30_k[2]>m30_d[2])
jy.closeallbuy(Symbol());
// 开空单
if(h4_rate[0].high>h4_bands_up[0] && m30_ma_xiao[0]<m30_ma_da[0] && m30_k[1]<m30_d[1] && m30_k[2]>m30_d[2])
jy.sellplus(Symbol(),LOTS,sl_point,tp_point,"sell",MAGIC);
// 平仓空单
if(m30_k[1]>m30_d[1] && m30_k[2]<m30_d[2])
jy.closeallsell(Symbol());
}
二、获取ZigZag顶点值
shuju.mqh:
class shuju
{
public:
shuju()
{
}
~shuju()
{
}
void ZigZag(double &data0[],int count,ENUM_TIMEFRAMES period,int ExtDepth,int ExtDeviation,int ExtBackstep);
void gettime(datetime &time[],int count);
void getlow(double &Low[],int count);
};
void shuju::ZigZag(double &data0[],int count,ENUM_TIMEFRAMES period,int ExtDepth,int ExtDeviation,int ExtBackstep)
{
int h = iCustom(Symbol(),period,"Examples/ZigZag",ExtDepth,ExtDeviation,ExtBackstep);
ArraySetAsSeries(data0,true);
CopyBuffer(h,0,0,count,data0);
IndicatorRelease(h);
}
void shuju::gettime(datetime &time[],int count)
{
ArraySetAsSeries(time,true);
CopyTime(Symbol(),0,0,count,time);
}
void shuju::getlow(double &Low[],int count)
{
ArraySetAsSeries(Low,true);
CopyLow(Symbol(),0,0,count,Low);
}
EA:
#include <myClass/shuju.mqh>
shuju sj;
input int InpDepth =12; // Depth
input int InpDeviation=5; // Deviation
input int InpBackstep =3; // Back Step
input int geshu = 10;
double zigzag[][4]; // 只计入顶点值
int OnInit()
{
ArrayResize(zigzag, geshu); // 设置新的第一维大小
return(INIT_SUCCEEDED);
}
void OnDeinit(const int reason)
{
}
void OnTick()
{
// ZigZag指标的顶点值为对应K线的最高/最低价,非顶点值为0
double zigzagzhi[];
int bars = Bars(Symbol(),0); // 返回K嫌数量
sj.ZigZag(zigzagzhi,bars,PERIOD_CURRENT,InpDepth,InpDeviation,InpBackstep);
datetime time[];
sj.gettime(time, bars);
double low[];
sj.getlow(low, bars);
int counter = 0;
for(int i=0; i<bars; i++)
{
if(counter>(geshu-1))
{
break;
}
if(zigzagzhi[i]>0)
{
zigzag[counter][0] = zigzagzhi[i];
zigzag[counter][1] = i;
zigzag[counter][2] = (double)time[i];
if(zigzagzhi[i] <= low[i]) // 低点
{
zigzag[counter][3] = 1;
}
else // 高点
{
zigzag[counter][3] = 2;
}
counter++;
}
}
}
三、逆势加仓EA
jiaoyi.mqh:
class jiaoyi
{
public:
int danshu(string symbol,ENUM_POSITION_TYPE type);
ulong buy(string symbol,double lots,int slpoint,int tppoint,string com,int magic);
ulong buyplus(string symbol,double lots,int slpoint,int tppoint,string com,int magic);
ulong zuijindan(string symbol,ENUM_POSITION_TYPE type,double &openprice,datetime &opentime,double &openlots,double &opensl,double &opentp,int magic);
double formatlots(string symbol,double lots);
void modifysltp(ENUM_POSITION_TYPE type,double sl,double tp);
};
int jiaoyi::danshu(string symbol,ENUM_POSITION_TYPE type)
{
int count = 0;
int total = PositionsTotal();
for(int i=total-1; i>=0; i--)
{
ulong ticket = PositionGetTicket(i);
if(ticket > 0)
{
if(PositionGetString(POSITION_SYMBOL)==symbol && PositionGetInteger(POSITION_TYPE)==type)
count++;
}
}
return(count);
}
ulong jiaoyi::buy(string symbol,double lots,int slpoint,int tppoint,string com,int magic)
{
MqlTradeRequest request = {};
MqlTradeResult result = {};
request.action = TRADE_ACTION_DEAL;
request.symbol = symbol;
request.type = ORDER_TYPE_BUY;
request.volume = lots;
request.deviation = 100;
request.type_filling = ORDER_FILLING_IOC;
request.price = SymbolInfoDouble(symbol,SYMBOL_ASK);
// SYMBOL_TRADE_STOPS_LEVEL 设置止损/止盈时,与当前价格的最小距离限制(以点为单位)
if(slpoint>SymbolInfoInteger(symbol,SYMBOL_TRADE_STOPS_LEVEL))
{
request.sl = SymbolInfoDouble(symbol,SYMBOL_ASK) - slpoint*SymbolInfoDouble(symbol,SYMBOL_POINT);
}
if(tppoint>SymbolInfoInteger(symbol,SYMBOL_TRADE_STOPS_LEVEL))
{
request.tp = SymbolInfoDouble(symbol,SYMBOL_ASK) + tppoint*SymbolInfoDouble(symbol,SYMBOL_POINT);
}
request.comment = com;
request.magic = magic;
// --- 发送请求
if(!OrderSend(request, result))
PrintFormat("OrderSend error %d", GetLastError()); // 如果不能发送请求,输出错误代码
// --- 显示操作信息
PrintFormat("retcode=%u deal=%I64u order=%I64u",result.retcode,result.deal,result.order);
return(result.order);
}
ulong jiaoyi::buyplus(string symbol,double lots,int slpoint,int tppoint,string com,int magic)
{
ulong ticket = 0;
int total = PositionsTotal();
for(int i=total-1; i>=0; i--)
{
if(PositionGetTicket(i)>0)
{
if(PositionGetString(POSITION_SYMBOL)==symbol && PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY && PositionGetInteger(POSITION_MAGIC)==magic && PositionGetString(POSITION_COMMENT)==com)
return(0);
}
}
ticket = buy(symbol,lots,slpoint,tppoint,com,magic);
return(ticket);
}
ulong jiaoyi::zuijindan(string symbol,ENUM_POSITION_TYPE type,double &openprice,datetime &opentime,double &openlots,double &opensl,double &opentp,int magic=0)
{
openprice = 0;
opentime = 0;
openlots = 0;
opensl = 0;
opentp = 0;
ulong ticket = 0;
int total = PositionsTotal();
for(int i=total; i>=0; i--)
{
if(PositionGetTicket(i) > 0)
{
if(PositionGetString(POSITION_SYMBOL)==symbol && PositionGetInteger(POSITION_TYPE)==type && PositionGetInteger(POSITION_MAGIC)==magic)
{
openprice=PositionGetDouble(POSITION_PRICE_OPEN);
opentime=(datetime)PositionGetInteger(POSITION_TIME);
openlots=PositionGetDouble(POSITION_VOLUME);
opensl=PositionGetDouble(POSITION_SL);
opentp=PositionGetDouble(POSITION_TP);
ticket=PositionGetInteger(POSITION_TICKET);
break;
}
}
}
return(ticket);
}
double jiaoyi::formatlots(string symbol,double lots)
{
double final_lots = 0;
double minilots=SymbolInfoDouble(symbol,SYMBOL_VOLUME_MIN);
double steplots=SymbolInfoDouble(symbol,SYMBOL_VOLUME_STEP);
if(lots<minilots)
return(0);
else
{
double temp = MathFloor(lots/minilots)*minilots;
final_lots = temp + MathFloor((lots-temp)/steplots)*steplots;
}
return(final_lots);
}
void jiaoyi::modifysltp(ENUM_POSITION_TYPE type,double sl,double tp)
{
int total = PositionsTotal();
for(int i=total-1; i>=0; i--)
{
if(PositionGetTicket(i)>0)
{
if(type==POSITION_TYPE_BUY)
{
// 止损止盈不等于原单子,才做修改。
if((NormalizeDouble(sl,(int)SymbolInfoInteger(Symbol(),SYMBOL_DIGITS))!=NormalizeDouble(PositionGetDouble(POSITION_SL),(int)SymbolInfoInteger(Symbol(),SYMBOL_DIGITS))||NormalizeDouble(tp,(int)SymbolInfoInteger(Symbol(),SYMBOL_DIGITS))!=NormalizeDouble(PositionGetDouble(POSITION_TP),(int)SymbolInfoInteger(Symbol(),SYMBOL_DIGITS))))
{
MqlTradeRequest request= {};
MqlTradeResult result = {};
request.action = TRADE_ACTION_SLTP;
request.position = PositionGetTicket(i);
request.symbol = Symbol();
request.sl = NormalizeDouble(sl,(int)SymbolInfoInteger(Symbol(),SYMBOL_DIGITS));
request.tp = NormalizeDouble(tp,(int)SymbolInfoInteger(Symbol(),SYMBOL_DIGITS));
if(sl<0)
request.sl = NormalizeDouble(PositionGetDouble(POSITION_SL),(int)SymbolInfoInteger(Symbol(),SYMBOL_DIGITS));
if(tp<0)
request.tp = NormalizeDouble(PositionGetDouble(POSITION_TP),(int)SymbolInfoInteger(Symbol(),SYMBOL_DIGITS));
if(!OrderSend(request,result))
PrintFormat("OrderSend error %d",GetLastError());
}
}
if(type==POSITION_TYPE_SELL)
{
if((NormalizeDouble(sl,(int)SymbolInfoInteger(Symbol(),SYMBOL_DIGITS))!=NormalizeDouble(PositionGetDouble(POSITION_SL),(int)SymbolInfoInteger(Symbol(),SYMBOL_DIGITS))||NormalizeDouble(tp,(int)SymbolInfoInteger(Symbol(),SYMBOL_DIGITS))!=NormalizeDouble(PositionGetDouble(POSITION_TP),(int)SymbolInfoInteger(Symbol(),SYMBOL_DIGITS))))
{
MqlTradeRequest request= {};
MqlTradeResult result = {};
request.action = TRADE_ACTION_SLTP;
request.position = PositionGetTicket(i);
request.symbol = Symbol();
request.sl = NormalizeDouble(sl,(int)SymbolInfoInteger(Symbol(),SYMBOL_DIGITS));
request.tp = NormalizeDouble(tp,(int)SymbolInfoInteger(Symbol(),SYMBOL_DIGITS));
if(sl<0)
request.sl = NormalizeDouble(PositionGetDouble(POSITION_SL),(int)SymbolInfoInteger(Symbol(),SYMBOL_DIGITS));
if(tp<0)
request.tp = NormalizeDouble(PositionGetDouble(POSITION_TP),(int)SymbolInfoInteger(Symbol(),SYMBOL_DIGITS));
if(!OrderSend(request,result))
PrintFormat("OrderSend error %d",GetLastError());
}
}
}
}
}
shuju.mqh:
class shuju
{
public:
shuju()
{
}
~shuju()
{
}
void getrates(MqlRates &rates[],int count);
void shuju::Bands(
double &Upper[],
double &Lower[],
double &Middle[],
int count,
string symbol, // 交易品种名称
ENUM_TIMEFRAMES period, // 周期
int bands_period, // 平均线计算周期
int bands_shift, // 指标平移
double deviation, // 标准差数
ENUM_APPLIED_PRICE applied_price // 价格或处理器类型
);
double getask();
};
void shuju::getrates(MqlRates &rates[],int count)
{
ArraySetAsSeries(rates, true);
CopyRates(Symbol(),PERIOD_CURRENT,0,count,rates);
}
void shuju::Bands(
double &Upper[],
double &Lower[],
double &Middle[],
int count,
string symbol, // 交易品种名称
ENUM_TIMEFRAMES period, // 周期
int bands_period, // 平均线计算周期
int bands_shift, // 指标平移
double deviation, // 标准差数
ENUM_APPLIED_PRICE applied_price // 价格或处理器类型
){
int h = iBands(symbol,period,bands_period,bands_shift,deviation,applied_price);
ArraySetAsSeries(Upper, true);
ArraySetAsSeries(Lower, true);
ArraySetAsSeries(Middle, true);
CopyBuffer(h,0,0,count,Middle);
CopyBuffer(h,1,0,count,Upper);
CopyBuffer(h,2,0,count,Lower);
IndicatorRelease(h);
}
double shuju::getask()
{
return(SymbolInfoDouble(Symbol(),SYMBOL_ASK));
}
EA:
#include <myClass/jiaoyi.mqh>
#include <myClass/shuju.mqh>
jiaoyi jy;
shuju sj;
input double init_lots = 0.1; // 初始下单量
input int loss_add_interbal_point = 100; // 亏损加仓间隔点数
input double loss_add_multiple = 2; // 亏损加仓下单倍数
input int syn_add_max_times = 5; // 同向单最多加仓次数
input int call_back_tp_point = 200; // 回调止盈点数
input int bollinger_period = 20;
input double bollinger_deviation =2;
input int MAGIC = 12345;
datetime buytime=0;
MqlRates rate[];
int OnInit()
{
sj.getrates(rate, 4);
buytime = rate[0].time;
return(INIT_SUCCEEDED);
}
void OnDeinit(const int reason)
{
}
void OnTick()
{
// 这里只展示开多单部分
sj.getrates(rate, 4);
double bandsup[], bandslow[], bandsmid[];
sj.Bands(bandsup,bandslow,bandsmid,4,Symbol(),PERIOD_CURRENT,bollinger_period,0,bollinger_deviation,PRICE_CLOSE);
int buydanshu = jy.danshu(Symbol(), POSITION_TYPE_BUY);
// 条件 buytime!=rate[0].time 是为了一根K线只开一个单。
if(buydanshu==0)
{
// 上一根K线的开盘价收盘价均脱离布林带下轨,且再上一根K线最低价触碰到布林带下轨,则开多单。
if(buytime!=rate[0].time && rate[1].open>bandslow[1] && rate[1].close>bandslow[1] && rate[2].low<bandslow[2])
{
if(jy.buyplus(Symbol(),init_lots,0,call_back_tp_point,"buy",MAGIC) > 0)
buytime = rate[0].time;
}
}
else
{
double open_price, open_lots, open_sl, open_tp;
datetime open_time;
jy.zuijindan(Symbol(),POSITION_TYPE_BUY,open_price,open_time,open_lots,open_sl,open_tp,MAGIC);
// 修改此前所有单的止盈价为最后一单的止盈价
jy.modifysltp(POSITION_TYPE_BUY, -1, open_tp); // 止损设为负值,则表示不修改止损
if(buydanshu<=syn_add_max_times && (open_price-sj.getask()) >= loss_add_interbal_point*Point())
{
// 逆势加仓
jy.buyplus(Symbol(),jy.formatlots(Symbol(), open_lots*loss_add_multiple),0,call_back_tp_point,"buy"+IntegerToString(buydanshu),MAGIC);
}
}
}