English 中文 Español Deutsch 日本語 Português Türkçe
Сетка и мартингейл: что это такое и как их использовать?

Сетка и мартингейл: что это такое и как их использовать?

MetaTrader 5Торговые системы | 17 сентября 2020, 09:55
12 198 100
Evgeniy Ilin
Evgeniy Ilin

Введение

В данной статье я хочу с помощью математики и программирования показать, что же на самом деле представляют из себя данные стратегии и действительно ли они так прибыльны, как думают многие. Будет математическая часть и практическая. В математической части я напишу формулы, с помощью которых можно будет посчитать математическое ожидание данных стратегий и другие важные параметры, которые, как я думаю, многие не берут в расчет. В практической части мы напишем простейшую сетку и простейший мартингейл, и сравним что, наши формулы говорят и что есть в реальности. Особенно статья будет полезна новичкам, так как первым делом, в основном, люди сталкиваются именно с этими стратегиями и начинают в них верить, что приводит к разочарованиям и бессмысленным тратам времени, как произошло и со мной в свое время. Если бы я не дружил с математикой, возможно, я до сих пор бы верил в эти стратегии. Но в этих стратегиях все же есть рациональное зерно, если грамотно на них посмотреть. Все это я попытаюсь вам доказать.


Что общего в этих двух стратегиях ?

Чтобы понять почему именно эти две стратегии так популярны, нужно понять, чего же хочет любой новичок, приходящий на форекс. В числе новичков всегда довольно большой процент математиков и мечтателей, думающих о быстром и легком обогащении за счет своего интеллекта, к которым относился в свое время и я. Обе эти стратегии реализуют видимость беспроигрышной торговли в виде графиков, все время идущих вверх в тестере стратегий. На многих участках истории котировок, даже при условии отсутствии всяких фильтров, можно так протестировать их, что будет казаться, что это Грааль. В любой сфере деятельности и в любом бизнесе есть моменты, на которых знающие люди могут вас развести и обогатиться за ваш счет. Так и здесь. Но на форексе таких обманок крайне много, а эти 2 стратегии самые наглядные и популярные тому доказательства. При первом использовании этих стратегий вы увидите, что они работают на всех валютных парах с просто невероятными профит-факторами и матожиданиями, и даже могут справиться с любыми спредами, так что кажется, что данный алгоритм вне рынка. Всё потому, что в их основе лежит чистая математика и никакой логики. Да, даже мне, опытному разработчику, сейчас до сих пор хотелось бы найти такие алгоритмы, которым неважно, куда идет цена, и выигрывать всегда. Математики — странные люди вообще, только дай повод сами, себе придумают все, что хочешь, и еще докажут это формулами, а потом — ой, а у меня вот тут ошибка )). В целом и общем эти две стратегии эксплуатируют иллюзию безубытка для того, чтобы убедить вас использовать их. Обе эти стратегии работают на любой валютной паре на любом периоде, точнее создают иллюзию работы,  и убеждают вас в простоте и работоспособности. Поняв всё в этих стратегиях, вы рано или поздно понимаете, что не знаете ничего ). Но это необходимо, так как только так вы начнете мыслить рационально, и начнете понимать истинную природу рынка и какие стратегии на самом деле нужно использовать.


Сетка и ее базовые формулы

Сетка ордеров была придумана с целью получения прибыли на любом рынке, неважно — падающий он или растущий — если ситуация такова, что присутствует ярко выраженное движение, то по задумке создателей сетка должна была с помощью хитрой системы открытия ордеров открывать ордера так, что, как не крутись, суммарно эти ордера в какой-то момент наберут достаточно профита, чтобы закрыть их все сразу. Проиллюстрирую сказанное на рисунке:

Здесь приведено 2 варианта для растущего и падающего рынка, соответственно. Независимо от того, какой вариант мы получим, мы все равно должны выиграть по задумке авторов. Те, кто применяют сетку, всегда говорят, мол, используйте отложенные ордера, что они исполняются по лучшей цене. Это так, но я считаю, что рыночные ордера ничем не хуже хотя — бы тем фактом, что можно спреды и проскальзывания контролировать в момент входа, и в случае чего можно немного подождать со входом, но в рамках этой стратегии лучше лимитники. У нас есть стартовая точка, относительно которой выставляются ордера, все что выше, то на покупку с шагом "s", все что ниже — на продажу, соответственно. Если цена достигает их, то они превращаются в рыночные. На рисунке я нарисовал уже открытые ордера, исходя из конкретной ситуации ценообразования. Лимитные можно не рисовать, так как они будут на тех же уровнях, просто будут уходить вверх и вниз до бесконечности. Но нам важны только открытые реальные ордера, ведь из их профита или убытка складывается общая прибыль или убыток соответственно. Чтобы обеспечить прибыль необходимо, чтобы каких то ордеров было больше, чем других, в "K" раз. Т.е. мы должны обеспечить K=a/d, где K>=K0 . К0 — это некий коэффициент, при достижении которого суммарный профит всех ордеров сетки превысит нулевой порог. Можно также просто посчитать текущий профит позиции или ордеров в случае MetaTrader 4. Либо же мы получим ситуацию, когда цена сразу же пойдет в какую-то сторону и мы зафиксируем прибыль, когда цена прошла "n" пунктов вверх или вниз. Этот коэффициент можно и посчитать, строго говоря, но обычно он просто подбирается вручную без проблем. Посчитать можно так:

  • Nl=d/s - 1
  • NP=(a+d)/s -1
  • Pr=Сумм(1,NP)(s*i)=(s+s*NP)*Np/2
  • Ls=Сумм(1,Nl)(s*j+ s*NP)=(s+s*Nl)*Nl/2+s*NP^2

Суммируя убыток или прибыль всех ордеров, можно увидеть, что эти суммы представляют из себя арифметические прогрессии, есть формула описывающая сумму арифметической прогрессии (используя ее первое и последнее слагаемое), она здесь и применяется.

Из условия Pr-Ls=0, решив это уравнение, можно найти "a", а далее посчитать K0=a/d. Также, используя эти формулы, можно добраться и до профит-фактора и матожидания тех торговых циклов,  в которых будут присутствовать открытые позиции и на покупку и на продажу.

  • Prf=Pr/Ls 
  • M=(Pr-Ls)/(Np+Nl)

Эти формулы вычисляют профит-фактор и матожидание конкретного торгового цикла, а не всего графика. При условии что наш график закончился в точке конца цикла, то наш профит фактор будет положительным. Циклом я называю отдельную сетку. Сетка построилась, отработала, позиции закрылись, а после строится новая сетка и так далее, можно до бесконечности при бесконечном депозите. Примерно вот так это все будет выглядеть на кривой баланса:


Здесь приведено упрощенное представление графика баланса робота сеточника при прогоне по истории. Всегда происходит какое-то количество циклов, которое выдерживает наш депозит и график идет вверх, но потом всегда происходит такой цикл, когда депозита не хватает, и вся наша видимая прибыль уходит брокеру. С точки зрения математики это считается неоконченным циклом, а неоконченный цикл всегда убыточен и его убыток перекроет всю вашу прибыль, которую вы заработали циклами, которые отработали до конца. При этом цикл может не окончиться еще из-за того, что не хватает ордеров на продолжение сетки. Дело в том, что у любого брокера есть ограничение на количество одновременно открытых ордеров в терминале или по какой-то конкретной паре, что заставляет нас учитывать эти особенности. Бесконечно сетку строить нельзя. Да и даже, если предположить, что вы можете это делать по каким то волшебным причинам, то все равно вы получите сценарий, который я нарисовал выше. В конце статьи я очень просто и быстро объясню математически, почему так происходит, так что всем все станет понятно и не останется никаких вопросов.


Мартингейл и его базовые формулы

Мартингейл, как и сетка, задумывался так, чтобы выигрывать независимо от того, куда пойдет рынок, и независимо от того, какие позиции и куда мы торгуем. В основе него лежит та же самая иллюзия вечной прибыли. Если мы открыли ордер и он прибыльный, то мы просто закрываем его и торгуем дальше. Как только у нас появляется проигрышный ордер, то следующему ордеру мы повышаем лот в "n" раз относительно проигрышной позиции, в случае если наш ордер прибыльный, мы просто закрываем его и сбрасываем лот на стартовое значение. А в случае, если ордер снова убыточный, то мы повторяем процедуру, только теперь уже лот увеличиваем в "n" раз относительно суммы лотов всех убыточных позиций, которые были в этом цикле, и так до тех пор, пока не получим прибыльную сделку. Последняя сделка в цикле всегда прибыльная и ее прибыль всегда перекрывает убыток проигрышных сделок, так наш график снова начинает состоять из циклов, и при условии, что график кончился вместе с последним циклом, то мы получаем положительное матожидание и профит-фактор. Не так важно, как мы открываем эти ордера и где. Желательно, чтобы эти ордера имели фиксированные прибыль и убыток, ну или просто закрывались по фиксированным стопам. Вот так будет выглядеть график баланса робота мартина:


Как видно, он очень похож на график баланса сетки, так как мартингейл работает циклами, как и сетка. Только открывает он по одному ордеру всегда и, пока тот не закроется, другой открывать не имеет права. Как и в случае сетки, однажды наступает момент, когда депозита не хватает, чтобы довести цикл до конца, и тогда происходит аварийное закрытие ордеров и, соответственно, слив депозита. Чтобы обеспечить прибыльные циклы нужно, чтобы прибыль последней сделки перекрывала убыток предыдущих сделок:

  • Nl
  • Np=1
  • Pr=L[Nl+Np]*TP[Nl+Np]*TickSize
  • Ls=Сумм(1,Nl)(L[i]*SL[i])*TickSize

Здесь прибыль вычисляется не в пунктах, а в единицах валюты вашего счета, потому как здесь используются манипуляции с лотом и считать в пунктах неудобно. Лоты конкретного ордера считаются с помощью рекурсии:

  • L[1]=StartLot
  • for(2,Nl) L[i]=(K*Сумм(1,i-1)(L[j]*SL[j]))/TP[i]

Где "K" — требуемый профит-фактор цикла. Здесь, конечно же, не учитываются спреды и комиссии, да и свопы тоже, конечно, но я не думаю, что это важно. Если возникнет потребность, то формулы можно модифицировать без проблем, но я не вижу в этом смысла. Формулы старался делать по аналогии с сеткой. SL и TP — это полученный убыток или желаемая прибыль ордера. Получить это определение можно, решив простейшее уравнение : K=(L[i]* TP[i])/Сумм(1,i-1)(L[j]*SL[j]).


Создаем и тестируем простейший сеточник

Для проверки предположений выше, вместе напишем простой сеточник и простой мартингейл на языке mql5, а потом протестируем их и посмотрим на результат. Начнем с сетки. Сначала добавим в наш шаблон пару удобных классов для работы с позициями:

#include <Trade\PositionInfo.mqh>
#include <Trade\Trade.mqh>
CPositionInfo  m_position=CPositionInfo();// trade position object
CTrade         m_trade=CTrade();          // trading object

Эти 2 библиотеки по умолчанию всегда есть в MetaTrader 5, поэтому проблем с компиляцией ни у кого не возникнет. 

Далее опишем все входные параметры, которые нам понадобятся:

///переменные сетки
input int MaxChannelSizePoints=500;//Max Of a+d
input int MinMoveToClose=100;//Mininum Move
input int GridStepPoints=20;//Grid Step In Points
input int BarsI=999;//Bars To Start Calculate
input double KClose=3.5;//Asymmetry
///

////////минимальная реализация торговли
input int SlippageMaxOpen=15; //Slippage For Open In Points
input double Lot=0.01;//Lot
input int MagicC=679034;//Magic
/////////

Первый блок реализует необходимые параметры сетки, а второй минимально реализует возможность торговли фиксированным лотом.

При старте эксперта нам понадобится проверка и восстановление параметров сетки с предыдущего сеанса, в случае, если работа завершилась некорректно. Это не обязательно, но лучше эти моменты продумывать заранее:

void DimensionAllMQL5Values()//////////////////////////////
   {
   ArrayResize(Time,BarsI,0);
   ArrayResize(High,BarsI,0);
   ArrayResize(Low,BarsI,0);
   }

void CalcAllMQL5Values()///////////////////////////////////
   {
   ArraySetAsSeries(High,false);                        
   ArraySetAsSeries(Low,false);                              
   ArraySetAsSeries(Time,false);                                                            
   CopyHigh(_Symbol,_Period,0,BarsI,High);
   CopyLow(_Symbol,_Period,0,BarsI,Low);
   CopyTime(_Symbol,_Period,0,BarsI,Time);
   ArraySetAsSeries(High,true);                        
   ArraySetAsSeries(Low,true);
   ArraySetAsSeries(Time,true);
   }

Этот код нужен для реализации предопределенных массивов, для того чтобы можно было провести стартовый анализ. А дальше нам эти массивы не понадобятся, мы будем их использовать только при стартовом расчете.

Восстановление будем производить вот так:

void RestoreGrid()//восстановим сетку в случае перезагрузки робота
   {
   DimensionAllMQL5Values();
   CalcAllMQL5Values(); 
   bool ord=PositionSelect(Symbol());
   if ( ord && int(PositionGetInteger(POSITION_MAGIC)) == MagicC )
      {
      GridStartTime=datetime(PositionGetInteger(POSITION_TIME));
      GridStartPrice=double(PositionGetDouble(POSITION_PRICE_OPEN));
      GridUpPrice=GridStartPrice;
      GridDownPrice=GridStartPrice;      
      
      for(int i=0;i<BarsI;i++)
         {
         if ( High[i] > GridUpPrice ) GridUpPrice=High[i];
         if ( Low[i] < GridDownPrice ) GridDownPrice=Low[i];
         if ( Time[i] < GridStartTime ) break;         
         }
      bCanUpdate=true;
      bTryedAlready=false;         
      }
   }

Для того чтобы отслеживать текущее состояние сетки, нужны вспомогательные переменные, которые отображают верхнюю и нижнюю цену за время существование сетки, а также стартовая цена сетки и время ее выставления.

datetime GridStartTime;//время создания сетки
double GridStartPrice;//стартовая цена сетки
double GridUpPrice;//верхняя цена коридора
double GridDownPrice;//нижняя цена коридора

И еще 2 булевые для того, чтобы сопровождать или обновлять переменные сетки в процессе движения цены, а также для дополнительных попыток закрытия сетки, если первая попытка закончилась неудачей.

bool bCanUpdate;//можно ли обновлять сетку
bool bTryedAlready;//была ли попытка закрыть позицию

Создание и обновление параметров сетки в процессе развития будет выглядеть так:

void CreateNewGrid()//создадим новую сетку
   {
   SymbolInfoTick(Symbol(),LastTick);  
   GridStartTime=TimeCurrent();
   GridStartPrice=LastTick.bid;
   GridUpPrice=GridStartPrice;
   GridDownPrice=GridStartPrice;
    
   double SummUp=LastTick.ask+double(GridStepPoints)*_Point;
   double SummDown=LastTick.bid-double(GridStepPoints)*_Point;
   
   while ( SummUp <= LastTick.ask+double(MaxChannelSizePoints)*_Point )
      {
      m_trade.BuyStop(Lot,SummUp,Symbol());
      SummUp+=double(GridStepPoints)*_Point;
      }
     
   while ( SummDown >= LastTick.bid-double(MaxChannelSizePoints)*_Point )
      {
      m_trade.SellStop(Lot,SummDown,Symbol());
      SummDown-=double(GridStepPoints)*_Point;
      }
   }

void UpdateGrid()//обновление параметров сетки
   {
   SymbolInfoTick(Symbol(),LastTick);
   if ( LastTick.bid > GridUpPrice ) GridUpPrice=LastTick.bid;
   if ( LastTick.bid < GridDownPrice ) GridDownPrice=LastTick.bid;
   }

Функции для закрытия позиций, очистки оставшихся лимитных ордеров и функция-предикат, засекающая условие закрытия сетки:

void ClosePosition()//закрыть позицию по символу
   {
   bool ord;
   ord=PositionSelect(Symbol());
   if ( ord && int(PositionGetInteger(POSITION_MAGIC)) == MagicC  )
      {
      if(m_position.SelectByIndex(0)) m_trade.PositionClose(m_position.Ticket());          
      }
   }

void CleanLimitOrders()//почистим лимитные ордера
   {
   int orders=OrdersTotal();
   for(int i=0;i<orders;i++)
      {
      ulong ticket=OrderGetTicket(i);
      if(ticket!=0)
         {
         m_trade.OrderDelete(ticket);
         }
      }
   }

bool bCanClose()//условие закрытия
   {
   if ( GridStartPrice == GridUpPrice && (GridStartPrice-GridDownPrice)/_Point >= MinMoveToClose ) return true;
   if ( GridStartPrice == GridDownPrice && (GridUpPrice-GridStartPrice)/_Point >= MinMoveToClose ) return true;
   
   if ( GridStartPrice != GridUpPrice && GridStartPrice != GridDownPrice 
   && (GridStartPrice-GridDownPrice)/(GridUpPrice-GridStartPrice) >= KClose 
   && (GridStartPrice-GridDownPrice)/_Point >= MinMoveToClose ) return true;
   if ( GridStartPrice != GridDownPrice && GridStartPrice != GridUpPrice 
   && (GridUpPrice-GridStartPrice)/(GridStartPrice-GridDownPrice) >= KClose
   && (GridUpPrice-GridStartPrice)/_Point >= MinMoveToClose ) return true;
   
   /*
   if ( GridUpPrice >= GridStartPrice+MaxChannelSizePoints*_Point 
   //|| GridDownPrice <= GridStartPrice-MaxChannelSizePoints*_Point ) return true;
   */
   return false;
   }

Последнее условие в функции-предикате я закомментировал, оно закрывает сетку в случае, если цена уехала за пределы сетки, его можете использовать по желанию, сути оно не меняет. Ну и осталось написать главную функцию для торговли:

void Trade()//основная функция где будем производить все действия
   {
   bool ord=PositionSelect(Symbol());
   
   if ( bCanUpdate ) UpdateGrid();
   
   if ( ord && bCanClose() )//если есть позиция и соблюдается условие закрытия
       {
       ClosePosition();
       CleanLimitOrders();
       bCanUpdate=false;
       bTryedAlready=true;
       }
   if ( bTryedAlready ) ClosePosition();
          
   if ( !bCanUpdate && !ord )
       {
       CleanLimitOrders();
       CreateNewGrid();
       bCanUpdate=true;
       bTryedAlready=false;
       }
   }

 Ну и определим, где что будем вызывать и что будем делать при инициализации советника:

int OnInit()
  {
  m_trade.SetExpertMagicNumber(MagicC);//установим магик для позиций
  RestoreGrid();//восстановим сетку если она есть
   return(INIT_SUCCEEDED);
  }

void OnTick()
  {
  Trade();
  }

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

Как видно предположения о убыточном цикле подтвердились. Сначала он довольно неплохо отрабатывает а потом наступает момент когда сетки не хватает и происходит убыточный цикл, который сводит всю прибыль до наоборот. На участках, где наблюдается неплохое трендовое движение, вы не увидите таких ситуаций, а вот там где доминирует флетовая составляющая, вы увидите слив за сливом, можете сами потестировать и посмотреть, в целом вы получите слив, так как у нас так или иначе еще есть спред.


Создаем и тестируем простейший мартин

Теперь, когда мы разобрались с сеткой, можно переходить к мартингейлу. Его код будет намного проще. Для работы с позициями также будем использовать библиотеки, которые мы использовали в сеточнике, второй раз этот код приводить смысла нет. Начнем сразу с входных параметров:

input int SLE=100;//Stop Loss Points
input int TPE=300;//Take Profit Points
input int SlippageMaxOpen=15; //Slippage For Open In Points
input double Lot=0.01;//Start Lot
input int MagicC=679034;//Magic
input int HistoryDaysLoadI=10;//History Deals Window Days

Для простоты я выбрал схему, при которой позиции закрываются строго по стоп лоссу или тейк профиту, единственное скажу про последнюю переменную, она нужна для того, чтобы не грузить всю историю ордеров каждый раз, а только какое-то необходимое окно (чисто для оптимизации), ну а остальные переменные, думаю всем, понятны и без слов.

В нашем советнике будет всего 2 функции:

double CalcLot()//вычисление лота
   {
   bool ord;
   double TotalLot=0;
   HistorySelect(TimeCurrent()-HistoryDaysLoadI*86400,TimeCurrent());
   for ( int i=HistoryDealsTotal()-1; i>=0; i-- )
      {
      ulong ticket=HistoryDealGetTicket(i);
      ord=HistoryDealSelect(ticket);
      if ( ord && HistoryDealGetString(ticket,DEAL_SYMBOL) == _Symbol 
      && HistoryDealGetInteger(ticket,DEAL_MAGIC) == MagicC 
      && HistoryDealGetInteger(ticket,DEAL_ENTRY) == DEAL_ENTRY_OUT )
         {
         if ( HistoryDealGetDouble(ticket,DEAL_PROFIT) < 0 )
            {
            TotalLot+=HistoryDealGetDouble(ticket,DEAL_VOLUME);
            }
         else
            {
            break;
            }
         }
      } 
   return TotalLot == 0 ? Lot: TotalLot;
   }


void Trade()//основная функция где будем производить все действия
   {
   bool ord=PositionSelect(Symbol());
   SymbolInfoTick(Symbol(),LastTick);
   if ( !ord )
      {
      if ( MathRand() > 32767.0/2.0 )
         {
         m_trade.Buy(CalcLot(),_Symbol,LastTick.ask,LastTick.bid-double(SLE)*_Point,LastTick.ask+double(TPE)*_Point);
         }
      else
         {
         m_trade.Sell(CalcLot(),_Symbol,LastTick.ask,LastTick.ask+double(SLE)*_Point,LastTick.bid-double(TPE)*_Point);
         }
      }
   }

Первая нужна для того, чтобы посчитать итоговый лот, которым мы будем открывать позицию, посмотрев в историю сделок. Если последняя сделка была убыточна, то следующий лот будет равен сумме лотов прошедших убыточных сделок, вплоть до первой прибыльной. Если последняя сделка прибыльная, то мы сбросим лот на первоначальное значение. В основной функции мы просто случайно будем открывать ордера в разных направлениях с фиксированными стопами, объемы будут вычисляться первой функцией. Ну и, для того, чтобы все это корректно работало, нужно назначить эксперту в инициализаторе свой магик, а основную функцию вызывать в обработчике OnTick, точно так же, как это было в сеточнике.

На этом сборка простейшего мартингейла завершена, теперь протестируем его и посмотрим на результат:


Картина похожа на ситуацию с сеткой, можно выделить циклы и видеть, как какое-то время все это работает, а потом наступает убыточный цикл, когда маржи уже не хватает для открытия следующей позиции и неизбежно происходит слив. Точно так же, как и с сеткой, где-то это будет работать, где-то нет, но в итоге вы опять получите слив как ни крути. Теперь, когда были рассмотрены обе стратегии и проверены на практике, можно даже пойти дальше и сделать математические выводы, которые даже приведут нас к более важным ответам, чем просто к пониманию этих двух стратегий.


Общая математика сетки и мартингейла

Почему общая математика сетки и мартингейла так важна на мой взгляд? Да потому, что поняв ее и впитав всю ее суть, вы навсегда распрощаетесь с целым рядом идей, которые никогда не принесут вам прибыли, хотя вам так хочется в них верить, ну или, по крайней мере, поймете, какие условия могут способствовать работоспособности этих стратегий. А также вы раз и навсегда поймете, почему голый мартингейл и сетка — это сливные стратегии, и почему же я так уверенно это говорю.

Представим, что любая стратегия состоит из бесконечного числа максимально простых стратегий, и в итоге при открытии любого ордера активируется какая-то из них. Будем считать, что эти ордера закрываются при фиксированном убытке или прибыли. Поставим им в соответствие массивы С[i] , Lot[i] , где размер этих массивов равен и стремится к бесконечности. Считаем что лот, которым играет каждая из стратегий, всегда разный. Также введем вероятность срабатывания какой-то из этих стратегий. PC[i], конечно же эти события образуют полную группу так, что Сумм(0,n)( PC[i] ) = 1. Все исходы этих событий образуют новые пространства событий S[i], T[i], которые представляют собой, соответственно, срабатывания по убытку и по профиту. У этих событий есть свои условные вероятности PS[i], PT[i], которые, конечно же, тоже образуют полную группу. Ниже приведу графическое представление сказанного:

Теперь рассмотрим любую отдельно взятую стратегию из этого списка и посчитаем ее матожидание.

  • M[i]=(PT[i]*TP-PS[i]*SL)*Lot[i]*TickSize.

Когда нам неизвестно направление движения цены в точках, где открывается позиция, то мы вправе сказать, что M[i]=0. Где M[i] — массив матожиданий конкретных стратегий. Иначе говоря, если мы не знаем, куда пойдет цена, то неважно, как мы торгуем, мы все равно получим "0" при количестве сделок стремящемся к бесконечности.

Теперь напишем общую формулу мат.ожидания:

  • M0=Сумм(0,n)(PC[i]*M[i])

Мы знаем, что при стремлении n к бесконечности, все M[i] стремятся к нулю, а значит все слагаемые нашей суммы при конечном количестве таких стратегий стремятся к "0", но при бесконечном количестве сделок. А это в свою очередь значит, что общее матожидание M0 по-прежнему равно "0". Если подумать дальше, то окажется, что бесконечный набор таких конечных наборов стратегий также будет равен нулю, так как суммируя бесконечное количество нулей и получим в итоге "0". В случае сетки величина лота везде одинакова, а в случае мартингейла она везде разная, но эти отличия никак не влияют на конечное матожидание. Обе стратегии можно описать вот этой общей формулой и даже не заморачиваться насчет комбинаторики и что, как и где открывается, и где закрывается. Все очень просто и понятно.

Но раз эти стратегии можно описать этой формулой, значит любую стратегию можно описать этой формулой, а, следовательно, напрашивается неумолимый вывод, который многие не захотят принимать, я уверен, но это в ваших интересах, уж поверьте. Вывод таков, что все стратегии, использующие вариацию и манипуляцию с объемами сделок, а также сколь угодно шаманскую систему открытия и закрытия ордеров, без знания примерного направления движения в момент открытия и закрытия сделок, или хотя-бы каких-то вспомогательных параметров рынка — несостоятельны по определению. То есть без правильного прогноза все ваши пляски с бубнами — это лишняя трата времени, и денег получается то же.


Как правильно использовать сетку и мартингейл

Начнем с сетки. Сетку лучше использовать тогда, когда известно, что рынок скоро начнет активное движение в какую-либо сторону, либо вероятность данного события сильно повышена, при этом есть риски поймать гэп, а гэпы с сетками очень плохо дружат, а если точнее  — совсем не дружат. Все потому, что ордера выставлены с определенным шагом, и может случиться так, что следующий тик пролетит мимо всех ордеров и появится далеко за сеткой. Конечно, так будет происходить очень редко, но это будет снижать показатели системы неизбежно. Размер сетки нужно выставлять равным либо чуть меньше прогнозируемого движения, при этом направление движения нам знать не надо, а лишь его примерную величину. График вашего баланса в случае успешного алгоритма детекта тренда будет выглядеть вот так:


Тренд далеко не всегда можно точно определить заранее, поэтому довольно часто будут возникать убыточные циклы, на рисунке он красный, да и просадка будет тоже немаленькая. У кого есть методы определения больших движений, могут с успехом пользоваться сеткой, строя сетку по своему сигналу. Я же пока этим вопросом не занимался, если у кого есть хорошие алгоритмы для детекта этих вещей, то был бы рад увидеть.

Далее определим, когда можно использовать мартингейл. Если у нас есть какой-либо сигнал, у которого матожидание равно "0", но при этом известно, что череда проигрышей такова, что вероятность прибыльной сделки близка к единице при определенном количестве проигрышей подряд, то этот сигнал можно будет использовать для мартингейла. График нашего баланса будет выглядеть так:

Но лично мое мнение —мартингейл использовать опасно в любом случае. Я считаю, что добиться таких условий, как я описал, практически нереально, с сеткой же мне кажется все проще, и, что самое главное, понятнее.


Заключение

В данной статье я старался наглядно и понятно рассказать, что же представляют из себя эти две стратегии, что в них общего, а самое главное — что в них плохого и что в них хорошего. Материал максимально прост и понятен для понимания даже новичка. Эта статья, скорее, для новичков, но сделаны выводы гораздо более важные, чем просто простая оценка стратегий и границ их применения. Сделаны общие математические выводы, которые позволят новичкам, да и думаю не только им, максимально продуктивно использовать свое время при разработке собственных торговых систем. Сама статья не приносит чего-то нового в понимание физики рынка, но, я думаю, остудит горячие головы тех, кто до сих пор пытается бездумно эксплуатировать эти принципы для их же собственного блага.

Прикрепленные файлы |
Easy_Grid.mq5 (14.19 KB)
Uncle_Martin.mq5 (6.47 KB)
Последние комментарии | Перейти к обсуждению на форуме трейдеров (100)
Evgeniy Ilin
Evgeniy Ilin | 14 янв. 2021 в 14:04
khorosh:

Здесь. Если сделаете, надеюсь мне подарите.)

Я глянул так бегло, довольно все незатейливо. Но мне представляется что наклон уровней плясать от высшего таймфрейма не самая хорошая идея, так как здесь уже я вижу как заложено предубеждение что раз тренд на высшем таймфрейме то значит наклон от него пляшет. Тренды не работают проверено, работает только коррекция после. В целом я считаю что тут машина может помочь. Я думаю нужно искать такой наклон уровней на текущем таймфрейме в фиксированном окне который дает минимум наклонных уровней но среднее количество ударов об эти уровни будет максимальным, так можно уйти от высших ТФ, тем более что как я уже сказал это только психологический момент. Так определим и наклон и максимально сильные каналы. По подробнее нужно еще почитать. В коде это реализовать тоже не проблема. Кстати там тоже на отскок советуют играть и в случае неудачи просто ждать отскока от следующего уровня или возврата цены к уровню и перевороту уровня.

Evgeniy Ilin
Evgeniy Ilin | 14 янв. 2021 в 14:20
Кстати я понял суть метода, в целом тут не каналы главное, просто наклонные каналы это наглядно. А обычные уровни слишком просто ) . В целом суть этого метода в том чтобы найти наиболее вероятные точки рикошета. Идея уровней тоже под собой содержит эту мысль. Просто с уровнями легче работать они не меняют свою цену, а вот наклонные постоянно меняются, и нужно достраивать их исходя из наклона. А зачем нужно так много уровней ? )) Дак все просто  раз уровень пробит значит со следующим повезет ))) Все как с обычными уровнями. В реальности же работает только инверт уровня и последующий ретест его же, этим отбиваются просадки. тоесть позиция в просадку уходит пробивая уровень а потом возвращается к нему. НЕ всегда правда, но очень часто. Это работает. Но опять же уровни это лишь абстракция, которой нет на самом деле. Нельзя не силу его рассчитать исходя из ударов, не длительность в будущем. Формул никаких нет, если только самопальные какие то у которых вообще нет никакой статистики. Только бектест, только хардкор...
khorosh
khorosh | 14 янв. 2021 в 15:51
Evgeniy Ilin:
Кстати я понял суть метода, в целом тут не каналы главное, просто наклонные каналы это наглядно. А обычные уровни слишком просто ) . В целом суть этого метода в том чтобы найти наиболее вероятные точки рикошета. Идея уровней тоже под собой содержит эту мысль. Просто с уровнями легче работать они не меняют свою цену, а вот наклонные постоянно меняются, и нужно достраивать их исходя из наклона. А зачем нужно так много уровней ? )) Дак все просто  раз уровень пробит значит со следующим повезет ))) Все как с обычными уровнями. В реальности же работает только инверт уровня и последующий ретест его же, этим отбиваются просадки. тоесть позиция в просадку уходит пробивая уровень а потом возвращается к нему. НЕ всегда правда, но очень часто. Это работает. Но опять же уровни это лишь абстракция, которой нет на самом деле. Нельзя не силу его рассчитать исходя из ударов, не длительность в будущем. Формул никаких нет, если только самопальные какие то у которых вообще нет никакой статистики. Только бектест, только хардкор...

То, что уровни наклонные, имеет логическое обоснование. Часто, когда уже допустим сформировался нижний экстремум - 1-я точка уровня, второй подход цены к уровню не доходит до лоу свечи, на которой образовалась 1-я точка, а доходит примерно до цены опен этого бара. Т.е. лоу получаются на разных высотах,- отсюда и получается наклонный уровень.

Evgeniy Ilin
Evgeniy Ilin | 14 янв. 2021 в 20:09
khorosh:

То, что уровни наклонные, имеет логическое обоснование. Часто, когда уже допустим сформировался нижний экстремум - 1-я точка уровня, второй подход цены к уровню не доходит до лоу свечи, на которой образовалась 1-я точка, а доходит примерно до цены опен этого бара. Т.е. лоу получаются на разных высотах,- отсюда и получается наклонный уровень.

На первый взгляд да, но чем этот уровень обусловлен ? В нашем мозге это просто линия и предположение о том что уровни могут быть и наклонные. А если углубиться в физику процесса что такое уровень вообще ? Я вот не знаю. Нет четкого определения. По классике это скопление лимит ордеров которое имеет большой суммарный объем который преодолеть очень тяжело, то есть нужен очень большой объем чтобы эти лимитники пробить или некоторое время пока они сами не рассосутся со временем. В обоих случая чтобы использовать эти уровни нужно знать объем этих ордеров что там висят и примерный период полураспада уровня или какой то аналог. Теории нет никакой. Только сказки и небылицы. Мол делай то и не делай это а почему фиг знает, потому что батя так сказал )). Нет статистики. Рынку выгодно поддерживать такие сказания о Царе Салтане чтобы толпу потихонечку стричь. Я просто человек науки, и доверяю только математике.

Evgeniy Ilin
Evgeniy Ilin | 14 янв. 2021 в 20:21
Будет статья, сов уже готов я покажу примерное направление в котором работать чтобы были глобальные бектесты плюсовые. Даже 2 статьи на 2 разные темы. Это не грааль но будет полезно очень тем кто хочет создать свою торговую систему глобального масштаба
Нейросети — это просто (Часть 5): Многопоточные вычисления в OpenCL Нейросети — это просто (Часть 5): Многопоточные вычисления в OpenCL
Мы уже познакомились с некоторыми типами реализации нейронных сетей. Легко заметить, что для каждого нейрона сети повторяются те же самые операции. И тут возникает желание воспользоваться возможностями многопоточных вычислений современной техники для ускорения процесса обучения нейронной сети. Об одном из вариантов такой реализации пойдет речь в данной статье.
Пишем Twitter-клиент для MetaTrader: Часть 2 Пишем Twitter-клиент для MetaTrader: Часть 2
Реализуем Twitter-клиент в виде MQL-класса, позволяющего отправлять твиты с картинками. Подключив всего один автономный include-файл, вы сможете публиковать твиты и выкладывать свои графики и сигналы.
Работа с таймсериями в библиотеке DoEasy (Часть 53): Класс абстрактного базового индикатора Работа с таймсериями в библиотеке DoEasy (Часть 53): Класс абстрактного базового индикатора
В статье рассмотрим создание класса абстрактного индикатора, который далее будет использоваться как базовый класс для создания объектов стандартных и пользовательских индикаторов библиотеки.
Работа с таймсериями в библиотеке DoEasy (Часть 52): Кроссплатформенность мультипериодных мультисимвольных однобуферных стандартных индикаторов Работа с таймсериями в библиотеке DoEasy (Часть 52): Кроссплатформенность мультипериодных мультисимвольных однобуферных стандартных индикаторов
В статье рассмотрим создание мультисимвольного мультипериодного стандартного индикатора Accumulation/Distribution. Чтобы программы, написанные под устаревшую платформу MetaTrader 4, основанные на данной библиотеке, могли нормально работать при переходе на MetaTrader 5, мы немного доработаем классы библиотеки касаемо индикаторов.