最后由 dark163 于 2021-6-4 12:03 编辑
本EA特点思路是利用布林带做突破,请多多测试研究,提出改进,勿用于实盘。
部分代码贴出:
#property copyright "Copyright © 2021, wes"
#property link ""
#property version "1.00"
#property description "wes grider EA V1.0。不要管过去发生了什么,你不是你的过去,你是你从过去所汲取的资源与能力。而这才是所有改变的根基。"
#property strict
input bool IsEnableDeal = true; //是否允许交易
input double Lot=0.01; //操作手数
input int gridStep=90; //网格步长点数
input double totalEquityLess = 200; //绝对止损总额(0禁用)
input double totalTakeProfit = 100; //每1手希望的获利
input double tpPoint = 1000; //带止盈时希望获利点数
input double slPoint = 500; //带止损时希望获利点数
input ENUM_TIMEFRAMES PERIOD = PERIOD_M1; //部署网格用布林带的时间帧
input int bandsMidMin = 50; //网格用布林带中轨部署最小距离
input int bandsMax = 500; //网格用布林带窄带识别最大值
input int maxLimits=10; //在一个方向上的限价订单数量
input int checkProfitTime = 3000; //检查利润毫秒数
bool isLog = false; //是否显示日志
bool LOTSKG = false; //复利开关
string sysName = "WES-Grid";
string prefix_graph="grider_"; //图像对象前缀
extern int EA_Magic = 32352; //魔术数
long MaxSPREAD = 30; //最大挂单点差
double ST = 0; //修正后步长
double allLots, buyLots, sellLots; //总手数,多单空单手数
double allProfit, buyProfit, sellProfit; //总盈利,单空单盈利
int buyNum, sellNum, allNum; //订单数量
int buyStopNum, selStoplNum; //挂单数量
double lastLot, lastType; //最后单手数,最后单类型
double lastOrderPrice; //最后订单价格
MqlTick lastPrice; //最后报价
double currBuyHigh = 0; //当前买入订单最高价
double currSellLow = 0; //当前卖出订单最低价
int OnInit(){
ST=gridStep;
if(_Digits==5 || _Digits==3){ // 修正网格步长
ST *=10;
SymbolInfoDouble(_Symbol, SYMBOL_POINT);
}
ST *= SymbolInfoDouble(_Symbol, SYMBOL_POINT);//修正价格
ObjectsDeleteAll(0, prefix_graph);
//EventSetTimer(60);
EventSetMillisecondTimer(checkProfitTime);
return(INIT_SUCCEEDED);
}
void OnTimer(){
Print("##################");
}
void OnTick(){
RefreshRates();
SymbolInfoTick(_Symbol, lastPrice);//获取最新报价
CountAllTrades();
checkLost();
checkTakeProfit();//检查利润
displayInfo();
if(!IsEnableDeal) return;//检查是否启用
if(!pdxIsNewBar()) return;//检查是否新分时柱
if(!existLimits()) setOrders();
}
bool existLimits() {//检测是否有订单及挂单
if(buyNum==0 && sellNum==0 && buyStopNum==0 && selStoplNum==0) return false;
return true;
}
bool pdxIsNewBar(){ // 检测是否柱开始的第一个分时,为了让EA每五分钟检查一次我们的状况,它应该在M5时间段启动
static datetime Old_Time;
datetime New_Time[1];
if(CopyTime(_Symbol,_Period,0,1,New_Time)>0){
if(Old_Time!=New_Time[0]){
Old_Time=New_Time[0];
return true;
}
}
return false;
}
void checkLost(){ ///检查绝对止损
double curProfit=0;
double profit=0;
int total = OrdersTotal();
for (int ti = total-1 ; ti >= 0 ; ti--){
bool sel = OrderSelect(ti,SELECT_BY_POS ,MODE_TRADES);
if(OrderSymbol()!=_Symbol) continue;
if(OrderMagicNumber()!=EA_Magic) continue;
profit += OrderProfit()+OrderCommission()+OrderSwap();
}
//if(buyNum+sellNum >= (int)maxLimits*2 ){//如果所有网格都已经进入订单,接受一定止损
// closeAllPos();
//}
if(profit< -MathAbs(totalEquityLess) && totalEquityLess!=0){//检查绝对止损(绝对止损不为0时为启用)
CloseAllOrders();
}
}
void checkTakeProfit(){ //离场逻辑
double curProfit=0;
double profit=0;
int total = OrdersTotal();
for (int ti = total-1 ; ti >= 0 ; ti--){
bool sel = OrderSelect(ti,SELECT_BY_POS ,MODE_TRADES);
if(OrderSymbol()!=_Symbol) continue;
if(OrderMagicNumber()!=EA_Magic) continue;
profit += OrderProfit()+OrderCommission()+OrderSwap();
}
// 计算获取逻辑
double takeval; // 希望获取利润, 已经交易手数差值
takeval = MathAbs(buyLots-sellLots) * totalTakeProfit;
if(isLog) Print("### take:",takeval, ", buyLots:",DoubleToString(buyLots,2), ", sellLots:",DoubleToString(sellLots,2),
", buyNum:",buyNum, ", sellNum:",sellNum,", H:",currBuyHigh,",L:",currSellLow, ",bid:",lastPrice.bid);
if(isLog) Print("################# profit:", profit);
if(profit> takeval){// && takeProfit>0){ // 达到获利则关闭
CloseAllOrders();
}
} |