#2179
26 минут назад, drobayura сказал:

Да это и есть цена входа high в BUY и low в SELL. ... "пропускает сигналы" - не открывает ордер на реальном счете. 

..."отрабатывает четко" а на демо счете открывает ордера по  high и low ценам свечи.

Если что то не так просто покажите как надо чтоб ордера открывались на high и low свечи.

#2180
3 часа назад, drobayura сказал:

Если что то не так просто покажите как надо чтоб ордера открывались на high и low свечи.

Ну открыть ордер можно по текущей цене открытия. Бид, или аск.

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

 

если вы найдете способ открываться на лоу и хай это будет настоящий грааль

#2181

Здравствуйте! Может кто нибудь помочь сделать этот тралл общим?

double OOP,SL;
   int b=0,s=0,tip,TicketB=0,TicketS=0;
   for(int i=0; i<OrdersTotal(); i++)
     {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
        {
         if(OrderSymbol()==Symbol())
           {
            tip = OrderType();
            OOP = NormalizeDouble(OrderOpenPrice(),Digits);
            if(tip==OP_BUY)
              {
               b++;
               TicketB=OrderTicket();
               if(Stoploss!=0   && Bid<=OOP - Stoploss   * Point) {if(OrderClose(OrderTicket(),OrderLots(),NormalizeDouble(Bid,Digits),slippage,clrNONE)) continue;}
               if(Takeprofit!=0 && Bid>=OOP + Takeprofit * Point) {if(OrderClose(OrderTicket(),OrderLots(),NormalizeDouble(Bid,Digits),slippage,clrNONE)) continue;}
               if(TrailingStop>0)
                 {
                  SL=NormalizeDouble(Bid-TrailingStop*Point,Digits);
                  if(SL>=OOP+TrailingStart*Point && (TrallB==0 || TrallB+TrailingStep*Point<SL)) TrallB=SL;
                 }
              }
            if(tip==OP_SELL)
              {
               s++;
               if(Stoploss!=0   && Ask>=OOP + Stoploss   * Point) {if(OrderClose(OrderTicket(),OrderLots(),NormalizeDouble(Ask,Digits),slippage,clrNONE)) continue;}
               if(Takeprofit!=0 && Ask<=OOP - Takeprofit * Point) {if(OrderClose(OrderTicket(),OrderLots(),NormalizeDouble(Ask,Digits),slippage,clrNONE)) continue;}
               TicketS=OrderTicket();
               if(TrailingStop>0)
                 {
                  SL=NormalizeDouble(Ask+TrailingStop*Point,Digits);
                  if(SL<=OOP-TrailingStart*Point && (TrallS==0 || TrallS-TrailingStep*Point>SL)) TrallS=SL;
                 }
              }
           }
        }
     }

 

#2182
8 часов назад, Lexa000 сказал:

Здравствуйте! Может кто нибудь помочь сделать этот тралл общим?

double OOP,SL;
   int b=0,s=0,tip,TicketB=0,TicketS=0;
   for(int i=0; i<OrdersTotal(); i++)
     {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
        {
         if(OrderSymbol()==Symbol())
           {
            tip = OrderType();
            OOP = NormalizeDouble(OrderOpenPrice(),Digits);
            if(tip==OP_BUY)
              {
               b++;
               TicketB=OrderTicket();
               if(Stoploss!=0   && Bid<=OOP - Stoploss   * Point) {if(OrderClose(OrderTicket(),OrderLots(),NormalizeDouble(Bid,Digits),slippage,clrNONE)) continue;}
               if(Takeprofit!=0 && Bid>=OOP + Takeprofit * Point) {if(OrderClose(OrderTicket(),OrderLots(),NormalizeDouble(Bid,Digits),slippage,clrNONE)) continue;}
               if(TrailingStop>0)
                 {
                  SL=NormalizeDouble(Bid-TrailingStop*Point,Digits);
                  if(SL>=OOP+TrailingStart*Point && (TrallB==0 || TrallB+TrailingStep*Point<SL)) TrallB=SL;
                 }
              }
            if(tip==OP_SELL)
              {
               s++;
               if(Stoploss!=0   && Ask>=OOP + Stoploss   * Point) {if(OrderClose(OrderTicket(),OrderLots(),NormalizeDouble(Ask,Digits),slippage,clrNONE)) continue;}
               if(Takeprofit!=0 && Ask<=OOP - Takeprofit * Point) {if(OrderClose(OrderTicket(),OrderLots(),NormalizeDouble(Ask,Digits),slippage,clrNONE)) continue;}
               TicketS=OrderTicket();
               if(TrailingStop>0)
                 {
                  SL=NormalizeDouble(Ask+TrailingStop*Point,Digits);
                  if(SL<=OOP-TrailingStart*Point && (TrallS==0 || TrallS-TrailingStep*Point>SL)) TrallS=SL;
                 }
              }
           }
        }
     }

 

Ну вы, вроде, уже сделали его общим, когда выложили его код сюда в топик.

 

Если вы имели в виду что-то другое, то, возможно, имеет смысл описать подробнее, чего именно вам хотелось бы добиться

#2183
1 час назад, Rigal сказал:

Ну вы, вроде, уже сделали его общим, когда выложили его код сюда в топик.

 

Если вы имели в виду что-то другое, то, возможно, имеет смысл описать подробнее, чего именно вам хотелось бы добиться

Мне нужно чтобы он траллил все открытые ордера по направлению в продажи общим профитом, то же самое в другом направлении. Например: открытую сеть в продажи закрывал всю общим профитом

#2184
4 минуты назад, Lexa000 сказал:

Мне нужно чтобы он траллил все открытые ордера по направлению в продажи общим профитом, то же самое в другом направлении. Например: открытую сеть в продажи закрывал всю общим профитом

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

Трал там явно в пунктах, причем пятизначных для пятизначного брокера, четырехзначных - для четырехзначного.

Я так понимаю, TrailingStop - это величина отката, на котором закрываем. TrailingStart - это профит в пунктах, после которого начинаем тралить, TrailingStep - шаг фиксации "максимума".
А дальше там есть вопросы по тейкам и стопам, например: они, вероятно, индивидуальные у всех ордеров, вы с ними как хотите поступать?

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

Поэтому проще описать, чего вы хотите. Написать это проще с нуля.

#2185
24 минуты назад, Rigal сказал:

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

Трал там явно в пунктах, причем пятизначных для пятизначного брокера, четырехзначных - для четырехзначного.

Я так понимаю, TrailingStop - это величина отката, на котором закрываем. TrailingStart - это профит в пунктах, после которого начинаем тралить, TrailingStep - шаг фиксации "максимума".
А дальше там есть вопросы по тейкам и стопам, например: они, вероятно, индивидуальные у всех ордеров, вы с ними как хотите поступать?

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

Поэтому проще описать, чего вы хотите. Написать это проще с нуля.

Вот его параметры

extern string txt1="Виртуальный Трейлинг"; //.
extern bool   virtualTral    = true;//Виртуал Трейлинг
input double     VTrailingStop  = 10.0;    // Длина трала
input double     VTrailingStart = 5.0;    // Минимальная прибыль для старта
input double     VTrailingStep  = 1.0;    // Шаг трала

так же в поинт умножен

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

#2186

Я хотел примерно так сделать, это первая часть на покупку

 double SetPoint=g_Point;
int P=0;
   if(virtualTral  && VTrailingStart>0 && TrailingStep<VTrailingStart)
     {
      double rtb=rata_price(0),tr=0;
      for(int i=0; i<OrdersTotal(); i++)
        {
         P=OrderSelect(iTrade,SELECT_BY_POS,MODE_TRADES);
         if(OrderType()==OP_BUY && OrderSymbol()==Symbol())
           
              {
               tr=rtb;
              }
            else
              {
               tr=OrderOpenPrice();
              }
            if(Bid-tr>VTrailingStart*SetPoint)
              {
               if(Bid-((VTrailingStart-TrailingStep)*SetPoint) > OrderStopLoss())
                 {
                  P=OrderModify(OrderTicket(),OrderOpenPrice(),Bid-((VTrailingStart-TrailingStep)*SetPoint),OrderTakeProfit(),0,Green);
                 }

 

Изменено 5 января, 2023 пользователем Lexa000

#2187
8 минут назад, Lexa000 сказал:

Я хотел примерно так сделать, это первая часть на покупку

 double SetPoint=g_Point;
int P=0;
   if(virtualTral  && VTrailingStart>0 && TrailingStep<VTrailingStart)
     {
      double rtb=rata_price(0),tr=0;
      for(int i=0; i<OrdersTotal(); i++)
        {
         P=OrderSelect(iTrade,SELECT_BY_POS,MODE_TRADES);
         if(OrderType()==OP_BUY && OrderSymbol()==Symbol())
           
              {
               tr=rtb;
              }
            else
              {
               tr=OrderOpenPrice();
              }
            if(Bid-tr>VTrailingStart*SetPoint)
              {
               if(Bid-((VTrailingStart-TrailingStep)*SetPoint) > OrderStopLoss())
                 {
                  P=OrderModify(OrderTicket(),OrderOpenPrice(),Bid-((VTrailingStart-TrailingStep)*SetPoint),OrderTakeProfit(),0,Green);
                 }

 

Ну примерно так и надо, если функция rata_price возвращает уровень безубытка всей позиции.
Только непонятно, зачем вот этот кусок

              {
               tr=rtb;
              }
            else
              {
               tr=OrderOpenPrice();
              }

 

#2188
5 минут назад, Rigal сказал:

Ну примерно так и надо, если функция rata_price возвращает уровень безубытка всей позиции.
Только непонятно, зачем вот этот кусок

              {
               tr=rtb;
              }
            else
              {
               tr=OrderOpenPrice();
              }

 

Этот кусок относится к коду  rata_price, а rata_price относится к модификации ордеров

#2189

Какая-то каша из невнятных формулировок и обрывков кода, если честно. Я не буду вам мешать. Если не справитесь - напишите здесь, чего вы хотите.

Желательно без упоминания, чего еще у вас есть, и как оно работает, сфокусируйтесь на конкретной задаче.
Я потрачу 15 минут, накидаю.

#2190
5 часов назад, Rigal сказал:

Какая-то каша из невнятных формулировок и обрывков кода, если честно. Я не буду вам мешать. Если не справитесь - напишите здесь, чего вы хотите.

Желательно без упоминания, чего еще у вас есть, и как оно работает, сфокусируйтесь на конкретной задаче.
Я потрачу 15 минут, накидаю.

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

Изменено 6 января, 2023 пользователем Lexa000

#2191
7 часов назад, Lexa000 сказал:

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

//+------------------------------------------------------------------+
//|                                                      Trailer.mq4 |
//|                        Copyright 2022, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2022, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict

input double VTrailingStartPips     =  10.0;    //Start trailing, pips
input double VTrailingStopPips      =  10.0;    //Traling stop, pips
input double VTrailingStepPips      =  1.0;     //Trailing step, pips

double trailingStartDouble, trailingStopDouble, trailingStepDouble;
double maxProfitDistance[] = {0.0, 0.0};
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit() {
      string baseCurrency = SymbolInfoString(Symbol(), SYMBOL_CURRENCY_BASE);
      string quoteCurrency = SymbolInfoString(Symbol(),  SYMBOL_CURRENCY_PROFIT);
      int pointsInPip = (Digits == 3 || Digits == 5) ? 10 : 1;
      if(baseCurrency == "XAU" || quoteCurrency == "XAU")
         pointsInPip = Digits == 2 ? 10 : 1;
      double pip = pointsInPip * Point();
      trailingStartDouble = VTrailingStartPips * pip;
      trailingStopDouble = VTrailingStopPips * pip;
      trailingStepDouble = VTrailingStepPips * pip;
   
      return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason){
//---
   
}
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick() {
   double lots[] = {0.0, 0.0};
   double profit[] = {0.0, 0.0};
   for(int i = OrdersTotal() - 1; i >= 0; i--) {
      if(OrderSelect(i, SELECT_BY_POS) && OrderSymbol() == Symbol()) {
         lots[OrderType()] += OrderLots();
         profit[OrderType()] += OrderProfit() + OrderSwap() + OrderCommission();
      }
   }
   for(int type = OP_BUY; type <= OP_SELL; type++) {
      if(lots[type] > DBL_EPSILON) {
         //we have open orders of this type
         double profitDistance = profit[type] / lots[type] / SymbolInfoDouble(Symbol(), SYMBOL_TRADE_TICK_VALUE) * SymbolInfoDouble(Symbol(), SYMBOL_TRADE_TICK_SIZE);
         if(maxProfitDistance[type] > 0.0 && maxProfitDistance[type] - profitDistance >= trailingStopDouble) {
            CloseAll(type);
         } else if(profitDistance >= trailingStartDouble) {
            double stepRoundedProfitDistance = trailingStartDouble + MathFloor((profitDistance - trailingStartDouble) / trailingStepDouble) * trailingStepDouble;
            maxProfitDistance[type] = MathMax(maxProfitDistance[type], stepRoundedProfitDistance);
         }
      } else {
         maxProfitDistance[type] = 0.0;
      }
   }
}
//+------------------------------------------------------------------+
void CloseAll(int _type) {
   for(int i = OrdersTotal() - 1; i >= 0; i--) {
      if(OrderSelect(i, SELECT_BY_POS) && OrderSymbol() == Symbol() && OrderType() == _type) {
         RefreshRates();
         if(!OrderClose(OrderTicket(), OrderLots(), (_type == OP_BUY ? Bid : Ask), 0, clrPurple))
            Print("Failed to close ticket #", OrderTicket(), ": ", GetLastError());  
      }
   }
}

Пипсы в настройках гарантированно старые, аналог четырехзначных.
Все остальное тривиально

Изменено 6 января, 2023 пользователем Rigal

#2192

image.png.ace1daf208dae821181f1d9986e487ea.png

Есть диапазон такого типа, в настройках задается к-во колен и процент риска. 

Советник выставляет на красной линии sell limit или sell stop, на голубой buy stop или buy limit 

При активации sell stop, и потом buy limit - на красной линии снова выставится ордер на продажу, потом при активации его на голубой - ордер на покупку и так указанное к-во колен (бай и селл считаются вместе).

 

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

 

Мой код выглядит так:

Спойлер

double getStartLot(double channel_w)
  {

   double loss = AccountBalance() * inp_max_lossPres / 100;
   Print("Max loss in balance is " + (string)loss);

   double prev_t = 0;
   double profit_t = 0;

   double profit_b;
   double profit_s;
   double l = 0;
   double totalSumLot_0 = 0;
   double totalSumLot_1 = 0;

   for(double j = 0; j < 1000; j++)
     {
      profit_t = 0;
      profit_b = 0;
      profit_s = 0;
      l = l+ 0.01;
         
      for(int i = 0; i < inp_max_levels; i++)
        {
        //прибавим к виртуальном бай и селл условное к-во лотов поочередно
         if(i % 2 == 0)
            totalSumLot_0 += (l * MathPow(inp_mult_grid, i));
         else
            totalSumLot_1 += (l * MathPow(inp_mult_grid, i));
        }
      double tickValue = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);
      profit_b = totalSumLot_0 * tickValue * channel_w;
      profit_s = totalSumLot_1 * tickValue * channel_w;
      profit_t = MathAbs(profit_b - profit_s);

//если профит больше или равно нужным потерям - остановимся на этом лоте
      if(profit_t >= loss)
        {
   Print("lot: " + (string)l + " loss: " + (string)prev_t);
   Print("profit_b: " + profit_b);
   Print("profit_s: " + profit_s);
   Print("totalSumLot_0: " + totalSumLot_0);
   Print("totalSumLot_1: " + totalSumLot_1);
   return (l);

        }
     }
   return (-1);
  }

 

Но, срабатывает не точно возле нужной границы

image.png.0d5a021fdad43c3422255610d7993223.png

 

Возможно есть мнения как решить мой кейс? 

 

#2193
1 час назад, ademen сказал:

Есть диапазон такого типа, в настройках задается к-во колен и процент риска. 

Советник выставляет на красной линии sell limit или sell stop, на голубой buy stop или buy limit 

При активации sell stop, и потом buy limit - на красной линии снова выставится ордер на продажу, потом при активации его на голубой - ордер на покупку и так указанное к-во колен (бай и селл считаются вместе).

Я немного потерялся.
На красной линии нельзя выставить sell limit или sell stop - выбор зависит от того, где цена.
Я читаю условие, как канал, внутри которого находится цена - и мне непонятно, как правильно прочитать: цена огораживается лимитками, или стопами?

 

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

#2194
4 минуты назад, Rigal сказал:

Я немного потерялся.
На красной линии нельзя выставить sell limit или sell stop - выбор зависит от того, где цена.
Я читаю условие, как канал, внутри которого находится цена - и мне непонятно, как правильно прочитать: цена огораживается лимитками, или стопами?

В зависимости от того, где цена - мы выставляем той или иной вид ордера.

Цена снизу огораживается снизу - лимитками, а сверху - стопами

 

 

Примерно так должно отработать, если у нас выставлено макс колен = 4 и убыток 10% (баланс 1 000 долл)

image.png.b5e81b5b5a5503fffa09e7a9f11911d4.png

 

18 минут назад, Rigal сказал:

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

В тестере я открывал в пределах одного дня и счет без комиссий, поэтому проблема скорее всего именно в алгоритме.

#2195
3 часа назад, ademen сказал:

В зависимости от того, где цена - мы выставляем той или иной вид ордера.

Цена снизу огораживается снизу - лимитками, а сверху - стопами

 

 

Примерно так должно отработать, если у нас выставлено макс колен = 4 и убыток 10% (баланс 1 000 долл)

image.png.b5e81b5b5a5503fffa09e7a9f11911d4.png

 

В тестере я открывал в пределах одного дня и счет без комиссий, поэтому проблема скорее всего именно в алгоритме.

внизу нельзя огородить sell limit, лимитка на продажу может быть выставлена только выше текущей цены.

Соответственно, снизу - только на покупку.

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

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

 

Но тогда я не особенно понимаю, какая там дальше логика?

#2196
8 часов назад, Rigal сказал:

внизу нельзя огородить sell limit, лимитка на продажу может быть выставлена только выше текущей цены.

Да, верно, должно быть sell stop на третьем ордере

8 часов назад, Rigal сказал:

Но тогда я не особенно понимаю, какая там дальше логика?

Логики нет, статистику собираю.

 

Вроде алгоритм должен быть не сложный: смоделировать движения цены в канале и посчитать лот, убыток, но на практике у меня не получается, как ни пробовал.

Игорь, может есть идея как сделать?

#2197
6 часов назад, ademen сказал:

Да, верно, должно быть sell stop на третьем ордере

Логики нет, статистику собираю.

 

Вроде алгоритм должен быть не сложный: смоделировать движения цены в канале и посчитать лот, убыток, но на практике у меня не получается, как ни пробовал.

Игорь, может есть идея как сделать?

я не про ту логику.

 

Я пытаюсь понять, что хочется сделать - и пока не понял, честно.

Давай попробуем в общих терминах, я попытаюсь описать, что я пока понял, поправляй:

- канал, где синяя линия выше текущей цены, а красная - ниже

Вариант один:

- мы выставляем на красной селл стоп и бай лимит. На синей, соответственно, бай стоп и селл лимит

- срабатывают ордера не одновременно: сначала срабатывает стоп, потом лимит (потому, что они активируются разными сторонами цены)

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

- После того, как пара сработала, цена может остаться за границей сине-красного канала, или вернуться в него

- дальше понимание обрывается

 

Вариант два:

- когда у нас ноль ордеров, мы выставляем два: на синей мы выставляем бай стоп, на красной - селл стоп (судя по вот этому рисунку)

20 часов назад, ademen сказал:

image.png.0d5a021fdad43c3422255610d7993223.png

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

- требуется посчитать лотность так, чтобы это число колен означало убыток определенной величины

 

Если речь о втором варианте, то задача не решается в общем виде, потому, что убыток будет в любой момент зависеть от траектории цены: для четного количества сделок в рынке убыток будет равен общему лоту помножить на (ширину канала + спред), помножить на цену тика, поделить на величину тика, плюс комиссия и свопы.

То есть, когда в рынке четное количество ордеров, убыток будет расти только за счет свопов и расширения спреда.

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

 

Теперь немного о том, как можно упростить модель :)

Пару ордеров можно заменить одним ордером со стопом ;) - потому, что пара ордеров образует лок, который НИКОГДА не выйдет в профит, зато будет копить свопы до закрытия (и отрицательное плечо свопа у любого брокера ВСЕГДА больше положительного, то есть кумулятивный своп этой пары - отрицателен).

 

Поправляй, если я где-то что-то не так понял, или разжуй яснее, я все это наощупь комментирую

 

Изменено 14 января, 2023 пользователем Rigal

#2198

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

Эта идея не реализуется накоплением пар ордеров одинаковой величины. Нужно или использовать вдвое больший лот на втором ордере и дальше (1-2-2-2-...), чтобы каждый следующий выход имел совокупный вес в сторону пробоя равный исходному лоту

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

 

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

Изменено 14 января, 2023 пользователем Rigal

#2199

Написал это все, перечитал еще раз исходное сообщение и, мне кажется, понял, что хочется посчитать:

 

лот ордера, при котором заданное количество ордеров на одной стороне канала, закрытое на другой стороне канала, принесет заданный убыток.

 

Эта задача решается так:

PnL = L * ChannelWidth * TickValue / TickSize

Соответственно, L = PnL * TickSize  / ChannelWidth / TickValue

 

Где L = это совокупный лот позиции.

Для ордеров равной лотности L = lots * N, где N - заданное количество колен

Глядя в код, я вижу, что там используется экспонента, то есть лотность колен может расти.

Соответственно, для множителя колена k: L = lots * (k^0 + k^1 + k^2 + ... + k^N-1)

Отсюда lots = L / (k^0 + k^1 + k^2 + ... + k^N-1)

 

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

 

глядя на код выше, опять же, попытаюсь накидать, как может выглядеть такое вычисление в коде:

input int    StepLimit       = 4;       //Лимит количества колен
input double LotMultiplier   = 1.6;     //Множитель лота


double lotCumulativeMultiplier = 0.0;   //посчитаем кумулятивный множитель для колен один раз на инициализации, просто ради оптимизации
double minLot, maxLot, lotStep;         //константы, вытащим их один раз
int lotPrecision = 2;

int OnInit() {
....
  lotCumulativeMultiplier = 1.0; //первое колено множится на один
  for(int i = 1; i < StepLimit; i++) //пропускаем нулевую степень, она добавлена предыдущей строчкой
  	lotCumulativeMultiplier += MathPow(LotMultiplier, i);
  minLot = SymbolInfo(Symbol(), MODE_MINLOT);
  maxLot = SymbolInfo(Symbol(), MODE_MAXLOT);
  lotStep = SymbolInfo(Symbol(), MODE_LOTSTEP);
  //пишу по памяти, константы MODE_ перепроверить!
  if(lotStep >= 0.1)
    lotPrecision = 1;
  if(lotsStep >= 1.0)
    lotPrecision = 0;
....
}
double getStartLot(double channel_w) {
  //я предполагаю, что ширина канала выше - в абсолютных единицах. Не в поинтах и не в пипсах
  double loss = AccountBalance() * inp_max_lossPres / 100; // сохранил, пересчет из процентов в деньги
  double totalLots = loss * SymbolInfo(Symbol(), MODE_TICKSIZE) / channel_w / SymbolInfo(Symbol(), MODE_TICKVALUE); // проверить константы, пишу прямо на сайте, могу перепутать MODE_TICKSIZE и проч
  double startLots = totalLots / lotCumulativeMultiplier;
  //теперь превратим это в приемлемое значение лота. Распишу в несколько строк, хотя можно свернуть в одну
  startLots = MathFloor(startLots / lotStep) * lotStep;
  startLots = MathMax(startLots, minLot);
  startLots = MathMin(startLots, maxLot);
  return (NormalizeDouble(startLots, lotPrecision);
}

 

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

- мы в любом случае вынуждены округлять финальный результат

 

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

Если же мы хотим максимально соблюсти геометрию сетки на каждом шаге, округляя лотность в ближайшую сторону (иногда вверх) - нам придется добавить дополнительный while цикл, в котором мы будем пересчитывать реальную лотность на каждом шаге и проверять ее на непревышение totalLots, понижать при необходимости стартовый лот на lotStep и повторять итерацию проверки.

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

Примерно так:

input int    StepLimit       = 4;       //Лимит количества колен
input double LotMultiplier   = 1.6;     //Множитель лота


double lotCumulativeMultiplier = 0.0;   //посчитаем кумулятивный множитель для колен один раз на инициализации, просто ради оптимизации
double minLot, maxLot, lotStep;         //константы, вытащим их один раз
int lotPrecision = 2;

int OnInit() {
....
  lotCumulativeMultiplier = 1.0; //первое колено множится на один
  for(int i = 1; i < StepLimit; i++) //пропускаем нулевую степень, она добавлена предыдущей строчкой
  	lotCumulativeMultiplier += MathPow(LotMultiplier, i);
  minLot = SymbolInfo(Symbol(), MODE_MINLOT);
  maxLot = SymbolInfo(Symbol(), MODE_MAXLOT);
  lotStep = SymbolInfo(Symbol(), MODE_LOTSTEP);
  //пишу по памяти, константы MODE_ перепроверить!
  if(lotStep >= 0.1)
    lotPrecision = 1;
  if(lotsStep >= 1.0)
    lotPrecision = 0;
....
}
double getStartLot(double channel_w) {
  //я предполагаю, что ширина канала выше - в абсолютных единицах. Не в поинтах и не в пипсах
  double loss = AccountBalance() * inp_max_lossPres / 100; // сохранил, пересчет из процентов в деньги
  double totalLots = loss * SymbolInfo(Symbol(), MODE_TICKSIZE) / channel_w / SymbolInfo(Symbol(), MODE_TICKVALUE); // проверить константы, пишу прямо на сайте, могу перепутать MODE_TICKSIZE и проч
  double startLots = NormalizeLots(totalLots / lotCumulativeMultiplier) + lotStep; //здесь намеренно прибавим lotStep, чтобы итерировать вниз на следующем шаге верификации, до полного удовлетворения
  while(true) {
    double sumLots = startLots;
    for(int i = 1; i < StepLimit; i++)
       sumLots += NormalizeLots(startLots * MathPow(LotMultiplier, i));
    if(sumLots <= totalLots)
       break;
    startLots -= lotStep;
  }
  return (startLots);
}
          
double NormalizeLots(double lots) {
  return (NormalizeDouble(MathMin(MathMax(MathRound(lots / lotStep) * lotStep, minLot), maxLot), lotPrecision));
}


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

 

Изменено 14 января, 2023 пользователем Rigal

#2200
9 часов назад, Rigal сказал:

Вариант два:

- когда у нас ноль ордеров, мы выставляем два: на синей мы выставляем бай стоп, на красной - селл стоп (судя по вот этому рисунку)

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

9 часов назад, Rigal сказал:

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

Эта идея не реализуется накоплением пар ордеров одинаковой величины. Нужно или использовать вдвое больший лот на втором ордере и дальше (1-2-2-2-...), чтобы каждый следующий выход имел совокупный вес в сторону пробоя равный исходному лоту

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

 

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

Да, есть мульт, деф значения 2.

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

 

Если на верхней границы открыли последний ордер - выше границы будет тп всех покупок и сл всех продаж, а на нижней границе сл всех покупок и тп всех продаж.

 

 

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

 

9 часов назад, Rigal сказал:
//я предполагаю, что ширина канала выше - в абсолютных единицах. Не в поинтах и не в пипсах

Что ты имеешь в виду? В абсолютных значения, имеется ввиду без знака „-“? В моем варианте кода используется пипс (5 знаков).

 

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

Завтра на работу возьму планшета и снова попробую разобраться.

 

#2201
42 минуты назад, ademen сказал:

Что ты имеешь в виду? В абсолютных значения, имеется ввиду без знака „-“? В моем варианте кода используется пипс (5 знаков).

Я имею в виду, дистанция

Например, между 1.22220 и 1.11110 дистанция в 1111 пипса, 11110 поинтов и абсолютная дистанция 0.11110

Я написал, полагая, что ширина канала передается абсолютной величиной. Если она в пипсах - домножь на величину пипса.

 

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

#2202
47 минут назад, ademen сказал:

выше сл всех продаж и тп всех покупок

Ты только помни, что сл продажи - это покупка. А тп покупки - это продажа.

Первые исполняются по аску, вторые - по биду. Поэтому, если поставить их все в одну точку, могут исполниться стопы и не исполниться тейки

#2203
11 часов назад, Rigal сказал:

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

Игорь, я проверил оба варианта, но к сожалению ни один не смог закрыть все сделки на противоположной стороне канала, или близко от него.

 

Возможно проблема в том, что позиции разнонаправленны? Я не увидел, где этот пункт обрабатывается в коде (если он есть - укажи, пожалуйста, на строчку, тогда будет яснее работа алгоритма). 

Твой алгоритм скорее всего классно бы работал в ситуации когда у нас сетка с бай или селл ордеров, у меня же идет чередование бай и селл

Для публикации сообщений создайте учётную запись или авторизуйтесь

Перейти к списку тем
Форум · 2.0.20260627.0025