Вместо CodeBase, в качестве небольшого отдыха

22 июня 2022, 21:34
Maxim Kuznetsov
0
38

Не всегда-же писать большие умные вещи :-) Иногда можно и отдохнуть-развлечься, набросать например мартингейл

код в прицепе иллюстрируют способ увеличения колен мартина и как-бы намекает что именно считать реальным убытком и на важность учёта обычно игнорируемого

Собственно сам по себе код, как есть:

//+------------------------------------------------------------------+
//|                                                         Yoda.mq5 |
//|                                                Maxim A.Kuznetsov |
//|                                          https://www.luxtrade.tk |
//+------------------------------------------------------------------+
#property copyright "Maxim A.Kuznetsov"
#property link      "https://www.luxtrade.tk"
#property version   "1.00"
/* N шагов увеличиваем SL/TP на спред*2^шаг, дальше удваиваем объём и возращаемся к прежним Sl/Tp
   проигрыш увеличивает шаг 
   выигрыш уменьшает
*/
#define MODULO 6
input double   LOTS=0.1;
input int      SLTP=120;
input int      SPREAD=5;

input long MAGIC=66;

#include <MT4Orders.mqh>
long ticket=-1;
int  step;
double maxBalance;

int OnInit()
{
   ticket=-1;
   step=0;
   maxBalance=AccountInfoDouble(ACCOUNT_BALANCE);
   return(INIT_SUCCEEDED);
}

void OnDeinit(const int reason)
{
}

void OnTick()
{
   double ask=SymbolInfoDouble(_Symbol,SYMBOL_ASK);
   double bid=SymbolInfoDouble(_Symbol,SYMBOL_BID);
   if (ticket!=-1 && OrderSelect(ticket,SELECT_BY_TICKET) && OrderCloseTime()!=0) {
      if (OrderProfit()<0) step+=2;
      else {
         if (AccountInfoDouble(ACCOUNT_BALANCE)>maxBalance) {
            maxBalance=AccountInfoDouble(ACCOUNT_BALANCE);
            step=0;
         } else {
            step--;
            if (step<0) step=0;
         }
      }
      ticket=-1;
   }
   if (ask-bid>=SPREAD*_Point) {
      return;
   }
   if (ticket==-1 && HasSignal()) {
      int op=SignalDirection();
      double price=(op==OP_BUY?ask:bid);
      double lots=Lots();
      int    sltp=SLTP();
      double sl=NormalizeDouble((op==OP_BUY?ask-sltp*_Point:ask+sltp*_Point)-(ask-bid),_Digits);
      double tp=NormalizeDouble((op==OP_BUY?bid+sltp*_Point:bid-sltp*_Point),_Digits);
      
      ticket=OrderSend(_Symbol,op,lots,op==OP_BUY?ask:bid,5,sl,tp,"",MAGIC);
      if (ticket>=0 && OrderSelect(ticket,SELECT_BY_TICKET)) {
         price=OrderOpenPrice();
         sl=NormalizeDouble((op==OP_BUY?price-sltp*_Point:price+sltp*_Point)-(ask-bid),_Digits);
         tp=NormalizeDouble((op==OP_BUY?price+sltp*_Point:price-sltp*_Point),_Digits);
         if (sl!=OrderStopLoss() || tp!=OrderTakeProfit()) {
            OrderModify(ticket,price,sl,tp,0);
         }
      }
   }
}

/// сигнал - есть всегда, торгуем прямо сразу
int HasSignal() {
   return 1;
}

/// торгуем в случайную сторону
int SignalDirection() {
   int r=MathRand();
   if (r>32768/2) {
      return OP_BUY;
   } 
   return OP_SELL;
}

/// рассчёт объёма от номера шага
double Lots()
{
   int maxStep=SLTP/(SPREAD);
   return NormalizeLots(LOTS*MathPow(2.0,(step/MODULO)));
}

/// дистанция Sl/Tp от номера шага
int SLTP()
{
   int maxStep=SLTP/(SPREAD);
   return SLTP+SPREAD*(int)MathPow(2,(step%MODULO));   
}

double NormalizeLots(double lots)
{
   double minLot=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN);
   double maxLot=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MAX);
   double lotStep=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_STEP);
   if (lots<=minLot) return minLot;
   lots=minLot+MathRound((lots-minLot)/lotStep)*lotStep;
   if (lots>=maxLot) return maxLot;
   return lots;
}

Резюмирая : единственный реальный убыток - это спред+своп+комиссия+проскальзывания. Приведённый код, исключительно для тестера и весь алгоритм просто отбивает спред обратно, растягивая  риски. И да, мартины ведутся не только объёмом, они вообще по риску в котором есть не только лоты

Сразу ответ на вопросы в личку: адаптировать такие способы к реальному рынку - очень дорого, там слишком тьма нюансов



 

Файлы:
Yoda.ex5  151 kb
Yoda.mq5  7 kb