//+------------------------------------------------------------------+ //| TurtleTrader.mq4 | //| Oschenker | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright 'Oschenker' #property link 'https://www.mql5.com' #property version '1.00' //#property icon 'RedValue 100x100.ico' //--- input parameters input int NExit = 10; //Donchian channel for exit breakout input int NST = 20; //Donchian channel for system-1 breakout input int NLT = 55; //Donchian channel for system-2 breakout input double MaxRisk = 0.01; //Max. deposit share at risk in one trade input double VolumeLimit = 4; //Max. amount of 'Units' per symbol input double AddingInterval = 1; //Adding interval (times ATR) input double StopLoss = 1; //Stop loss (times ATR) input double TakeProfit = 1; //Take profit (times ATR) input int Deviation = 3; //Allowable trade slippage input string String = '-----------------------------------------------'; //SAR parameters--------------------------------------- input bool SARFlag = false; //Use SAR-system to trail SL input double AFStep = 0.02; //SAR system step input double AFCap = 0.2; //SAR system cap

// global variables int Direction; long PositionID; double Unit; double PriceOpen; double MaxExit; double MinExit; double MaxST; double MinST; double MaxLT; double MinLT; double SL; double TP; double EP; double AF; double ATR; datetime CheckTime; datetime CheckTimeSAR; bool PrevBreakout;

//+------------------------------------------------------------------+ //| Expert AverageTR function | //+------------------------------------------------------------------+ double AverageTR(double high, double low, double prev_close) { // calculate average true range double true_range = fmax(high - low, fmax(high - prev_close, prev_close - low)); double account_equity = AccountInfoDouble(ACCOUNT_EQUITY); double tick_value = SymbolInfoDouble(Symbol(), SYMBOL_TRADE_TICK_VALUE); double volume_min = SymbolInfoDouble(Symbol(), SYMBOL_VOLUME_MIN); if(ATR == 0) ATR = true_range; ATR = (19 * ATR + true_range) / 20; // adjust ATR for dollar volatility to calculate Unit (trade value) int digits = (int)log10(volume_min); // number of digits after dechimal points in Min Value allowed Unit = fmin(VolumeLimit, fmax(volume_min, NormalizeDouble((MaxRisk * account_equity * Point()) / (ATR * tick_value), digits))); return(ATR); } //+------------------------------------------------------------------+ //| Expert SARTrailing function | //+------------------------------------------------------------------+ bool SARTrailing(double high, double low) { // calculate new SL value switch(Direction) { // position is BUY case 1: if(high > EP) { AF = fmin(AFCap, AF + AFStep * ATR * 1000); EP = high; } SL = SL + AF * (EP - SL); Print(EP, ' ', SL); break; // position is SELL case -1: if(low < EP) { AF = fmin(AFCap, AF + AFStep * ATR * 1000); EP = low; } SL = SL - AF * (SL - EP); Print(EP, ' ', SL); break; } Request.action = TRADE_ACTION_SLTP; Request.symbol = Symbol(); Request.sl = SL; Request.position = PositionGetInteger(POSITION_TICKET); if(OrderCheck(Request, Check) && Check.retcode == 0) { if(!OrderSend(Request, Results) || Results.retcode != 10009) return(false); else return(true); } else { if(Check.retcode == 10019) Print('There is not enough money to complete the request'); if(Check.retcode == 10025) Print('No changes in request'); if(Check.retcode == 10014) Print('Invalid volume in the request'); return(false); }
return(false); } //+------------------------------------------------------------------+ //| Expert Breakout function | //+------------------------------------------------------------------+ int Breakout(double price, double max, double min) { int direction; // check breakout direction = 0; if(price > max) direction = 1; if(price < min) direction = -1; return(direction); }

//+------------------------------------------------------------------+ //| Expert MaxMin function | //+------------------------------------------------------------------+ bool MaxMin() { // calculate price level of minimum and maximum over last n_... bars MaxLT = iHigh(Symbol(), 0, NLT); MinLT = iLow(Symbol(), 0, NLT); for(int i = 2; i <= NLT; i++) { if(iHigh(Symbol(), 0, NLT - i) > MaxLT) MaxLT = iHigh(Symbol(), 0, NLT - i); if(iLow(Symbol(), 0, NLT - i) < MinLT) MinLT = iLow(Symbol(), 0, NLT - i); if(i == NExit) { MaxExit = MaxLT; MinExit = MinLT; } if(i == NST) { MaxST = MaxLT; MinST = MinLT; } } //Print('Exit ', MaxExit, ' ', MinExit); //Print('ST ', MaxST, ' ', MinST); //Print('LT ', MaxLT, ' ', MinLT); return(true); }

//+------------------------------------------------------------------+ //| Expert Trade Function | //+------------------------------------------------------------------+ bool Trade(int direction, double volume) { Request.action = TRADE_ACTION_DEAL; Request.symbol = Symbol(); Request.volume = volume; Request.deviation = Deviation; if(direction == 1) { Request.type = ORDER_TYPE_BUY; Request.price = EP = Ask; Request.sl = SL = Request.price - StopLoss * ATR; if(TakeProfit != 0) Request.tp = TP; } if(direction == -1) { Request.type = ORDER_TYPE_SELL; Request.price = EP = Bid; Request.sl = SL = Request.price + StopLoss * ATR; if(TakeProfit != 0) Request.tp = TP; } if(OrderCheck(Request, Check) && Check.retcode == 0) { if(!OrderSend(Request, Results) || Results.retcode != 10009) return(false); PriceOpen = Results.price; return(true); } else { if(Check.retcode == 10025) Print('No changes in request'); if(Check.retcode == 10019) Print('There is not enough money to complete the request'); if(Check.retcode == 10014) Print('Invalid volume in the request'); return(false); } return(true); }

//+------------------------------------------------------------------+ //| Expert DrawLevel function | //+------------------------------------------------------------------+ bool DrawLevels(datetime lastbar_time) { // wait for new bar string name; uchar arrow_code; color clr; double level; // 1 create Exit Max arrow name = 'MaxExit' + (string)lastbar_time; arrow_code = 158; level = MaxExit; clr = clrRed; if(ObjectCreate(0, name, OBJ_ARROW, 0, lastbar_time, level)) { ObjectSetInteger(0, name, OBJPROP_ARROWCODE,arrow_code); ObjectSetInteger(0, name, OBJPROP_COLOR,clr); ObjectSetInteger(0, name, OBJPROP_BACK, false); } else return(false);

// 2 create Exit Min arrow 
name = 'MinExit' + (string)lastbar_time;
arrow_code = 158;
level = MinExit;
clr = clrRed;
if(ObjectCreate(0, name, OBJ_ARROW, 0, lastbar_time, level))
  {
   ObjectSetInteger(0, name, OBJPROP_ARROWCODE,arrow_code); 
   ObjectSetInteger(0, name, OBJPROP_COLOR,clr); 
   ObjectSetInteger(0, name, OBJPROP_BACK, false); 
  }
else return(false);

// 3 create ST Max arrow 
name = 'MaxST' + (string)lastbar_time;
arrow_code = 159;
level = MaxST;
clr = clrBlue;
if(ObjectCreate(0, name, OBJ_ARROW, 0, lastbar_time, level))
  {
   ObjectSetInteger(0, name, OBJPROP_ARROWCODE,arrow_code); 
   ObjectSetInteger(0, name, OBJPROP_COLOR,clr); 
   ObjectSetInteger(0, name, OBJPROP_BACK, false); 
  }
else return(false);

// 4 create ST Min arrow 
name = 'MinST' + (string)lastbar_time;
arrow_code = 159;
level = MinST;
clr = clrBlue;
if(ObjectCreate(0, name, OBJ_ARROW, 0, lastbar_time, level))
  {
   ObjectSetInteger(0, name, OBJPROP_ARROWCODE,arrow_code); 
   ObjectSetInteger(0, name, OBJPROP_COLOR,clr); 
   ObjectSetInteger(0, name, OBJPROP_BACK, false); 
  }
else return(false);

// 5 create LT Max arrow 
name = 'MaxLT' + (string)lastbar_time;
arrow_code = 167;
level = MaxLT;
clr = clrGreen;
if(ObjectCreate(0, name, OBJ_ARROW, 0, lastbar_time, level))
  {
   ObjectSetInteger(0, name, OBJPROP_ARROWCODE,arrow_code); 
   ObjectSetInteger(0, name, OBJPROP_COLOR,clr); 
   ObjectSetInteger(0, name, OBJPROP_BACK, false); 
  }
else return(false);

// 6 create LT Max arrow 
name = 'MinLT' + (string)lastbar_time;
arrow_code = 167;
level = MinLT;
clr = clrGreen;
if(ObjectCreate(0, name, OBJ_ARROW, 0, lastbar_time, level))
  {
   ObjectSetInteger(0, name, OBJPROP_ARROWCODE,arrow_code); 
   ObjectSetInteger(0, name, OBJPROP_COLOR,clr); 
   ObjectSetInteger(0, name, OBJPROP_BACK, false); 
  }
else return(false);

return(true); 

}

//+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { ENUM_ACCOUNT_MARGIN_MODE marginMode; marginMode = (ENUM_ACCOUNT_MARGIN_MODE)AccountInfoInteger(ACCOUNT_MARGIN_MODE); if(marginMode == ACCOUNT_MARGIN_MODE_RETAIL_HEDGING) { Print('This EA doesn't work in HEDGING mode'); return(INIT_FAILED); } double volume_limit = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_LIMIT); if(volume_limit < VolumeLimit && volume_limit != 0) { Print('Volume limit exceed Maximal volume limit ', volume_limit); return(INIT_FAILED); } return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { // clear all objects from the chart ObjectsDeleteAll(0, -1, -1); // remove comments, if any ChartSetString( 0, CHART_COMMENT, ''); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { if(CopyRates(Symbol(), 0, 0, NLT, Rates) <= 0) Print('There is no price data'); else { double price = Close[NLT - 1]; datetime lastbar_time = (datetime)iTime(Symbol(), PERIOD_CURRENT, 0); if(CheckTime != lastbar_time) // wait for another bar to close { CheckTime = lastbar_time; // calculate volatility (ATR) ATR = AverageTR(High[NLT - 2], Low[NLT - 2], Close[NLT - 3]); Comment('ATR = ' + DoubleToString(ATR, 4) +' ' + 'Unit = ' + DoubleToString(Unit, 2) + ' ' + 'Previous breakout = ' + (string)PrevBreakout); // calculate levels for Donchian channel if(!MaxMin()) Print('MaxMin failed'); else if(!DrawLevels(lastbar_time)) Print('Level drawing failed'); }

    // if there is open position   
    if(OrdersTotal() > 0)
      {
       PositionID = OrderGetTicket(0);
       // if total volume opened < MaxVolume - add positions after every 0.5 * ATR price move
       double position_volume = OrderGetInteger(POSITION_VOLUME);
       if((position_volume + Unit) < VolumeLimit)
           {
            // price is higher than price of last open position
            if((price - PriceOpen) * Direction > AddingInterval * ATR)
               {
                if(!Trade(Direction, Unit)) Print('Unit addition is failed');
               }
           }
       // exit all positions after backward breakout MMExit
       int back_ward = Breakout(price, MaxExit, MinExit);
       if(back_ward == -1 * Direction)
         {
          if(Trade(back_ward, position_volume)) Direction = 0;
         }
       if(SARFlag && CheckTimeSAR != lastbar_time) // wait for another bar to close
         {
          CheckTimeSAR = lastbar_time;
          SARTrailing(High[NLT - 2], Low[NLT - 2]);
         }
      }
    else
      {
       // if previous breakout was successful breakout
       if(PrevBreakout)
         {
          // check back-ward breakout of 10 days extremum
          int back_ward = Breakout(price, MaxExit, MinExit);
          if(back_ward == -1 * Direction)
            {
             Direction = 0;
             PrevBreakout = false;
             return;
            }
          int LT_breakout = Breakout(price, MaxLT, MinLT);
          if(LT_breakout == Direction)
            {
             PrevBreakout = false;
             if(!Trade(Direction, Unit)) Print('Trade failed');
            }
          return;
         }
       else
         {
          // if previous breakout was not successful breakout - store breakout direction and trade
          Direction = Breakout(price, MaxST, MinST);
          if(Direction == 0) return;
          PrevBreakout = true;
          TP = price + Direction * TakeProfit * ATR;
          if(!Trade(Direction, Unit)) Print('Trade failed');
         }
       return;
      }
   }

} //+------------------------------------------------------------------+ //| Trade function | //+------------------------------------------------------------------+ void OnTrade() { int deals_num; ulong tiket; string deal_comment; if(HistorySelectByPosition(PositionID)) { deals_num = HistoryDealsTotal(); //--- total deals number in the list for( int i=0; i < deals_num && !IsStopped(); i++) { tiket = HistoryDealGetTicket(i); if(HistoryDealGetString(tiket, DEAL_COMMENT, deal_comment) && StringFind(deal_comment, 'sl', 0) != -1) { Direction = 0; PrevBreakout = false; PositionID = 0; } if(HistoryDealGetString(tiket, DEAL_COMMENT, deal_comment) && StringFind(deal_comment, 'tp', 0) != -1) { Direction = 0; PrevBreakout = true; PositionID = 0; } } }
}

//+------------------------------------------------------------------+

TurtleTrader EA for MT5 - Donchian Channel Breakout Strategy

原文地址: https://www.cveoy.top/t/topic/ne4K 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录