Forex Forum - Независимый форекс форум для трейдеров

Forex Forum - Независимый форекс форум для трейдеров (https://forexsystemsru.com/)
-   Язык программирования MQL4 (https://forexsystemsru.com/yazyk-programmirovaniya-mql4-f72/)
-   -   Помогите с кодом пожалуйста... (https://forexsystemsru.com/yazyk-programmirovaniya-mql4/33798-pomogite-s-kodom-pozhaluista.html)

Моргана 28.04.2010 10:44

Помогите с кодом пожалуйста...
 
Как прописать в коде, чтобы лот после убыточной сделки увеличивался в зависимости от величины этого убытка? У меня ТР стабильный, а убытки разные - могут быть -100, могут -30 или например -560 и т.д. А прибыль всегда одна и та же. Соответственно в коде прописала:
lot=NormalizeDouble(OrderProfit()/Profit,1);
где OrderProfit это отрицательный результат, Profit - значение моей стабильной прибыли на одну сделку.
В общем здесь вопросов нет, всё работает как надо...
Проблема такая: как сделать чтобы при череде убытков (2 и больше) он суммировал эти отрицательные значения и в конце концов увеличивал лот соответственно так чтобы прибыльная сделка после этой череды покрыла все эти убытки? :question:
Подскажите пожалуйста, буду очень благодарна!

cmillion 30.04.2010 22:05

Находим последний закрывшийся ордер:
PHP код:

if(сделка закрылась)
{
   
double Loss;
   
int i=OrdersHistoryTotal()-1;
   if(
OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)==true)
   {                                     
      if (
OrderProfit()<0Loss+=OrderProfit();
      else 
Loss=0;
   }


Loss - общий убыток на данный момент

А теперь вычисляем лот для покрытия убытка в зависимости от накопленного Lossa как отношение Lossa к требуемому профиту.

Моргана 01.05.2010 08:57

Спасибо большое, попробую!

cmillion 01.05.2010 09:06

Цитата:

Сообщение от Моргана (Сообщение 102421)
Спасибо большое, попробую!

Нужна будет помощь обращайтесь.

[Ссылки могут видеть только зарегистрированные пользователи. Зарегистрироваться...]

Удачи!

Моргана 02.05.2010 15:44

Еще раз спасибо, всё получилось)

machzelet 02.05.2010 18:13

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

Идея такова:
Стоп-лосс рассчитавыется формулой в процентном соотношении максимально допустимого убытка от депозита с учетом валютного коэффициента (на один пипс) и величины тогруемого лота (аля ММ).

Пример:
StopLoss = (Депозит * Процент риска) / (Коэфф. валюты * Коэфф. лота)

Допустим:
Депозит = 356 у.е.
Процент риска = 30 (максимальный убыток, который мы готовы понести за одну сделку)
Коэфф. валюты = 37 (скажем, если счет не долларовый, а в шекелях, то на паре евро-бакса один пипс равен 0.37 шекеля * 100)
Коэфф. лота = 3 (при лоте 0,03 * 100)

Итак, StopLoss = (356 * 30) / (37 * 3) = 96,216216216216216216216216216216
Берем только целое число и получаем наш стоп-лосс равный 96 пипсам.

Буду очень благодарен за помощь.

machzelet 02.05.2010 18:48

Всё, уже сам написал ))

cmillion 02.05.2010 19:16

Цитата:

Сообщение от machzelet (Сообщение 102863)
Всё, уже сам написал ))

Я рад за Вас! Если нужна будет помощь, нажмите здесь:



Удачи!

machzelet 02.05.2010 20:45

cmillion, спасибо ))
Теперь возникла другая проблема - хочу добавить в советник функцию определения последней сделки закрытой по стоп-лоссу, чтобы с ее помощью высчитать размер следующей сделки. Только вот никак не могу найти функцию, которая определяет последнюю сделку, которая закрылась по стоп-лоссу (((
Вроде бы эта - OrderStopLoss(), но что в скобках прописать, чтобы советник определил?

Вообще, то что мне нужно, следующее:
kLots = величина последней стоповой сделки * коэффициент валюты / тейк профит (в пипсах)

Не поможете с этим?
Заранее благодарен.

cmillion 02.05.2010 20:56

Цитата:

Сообщение от machzelet (Сообщение 102903)
cmillion, спасибо ))
Теперь возникла другая проблема - хочу добавить в советник функцию определения последней сделки закрытой по стоп-лоссу, чтобы с ее помощью высчитать размер следующей сделки. Только вот никак не могу найти функцию, которая определяет последнюю сделку, которая закрылась по стоп-лоссу (((
Вроде бы эта - OrderStopLoss(), но что в скобках прописать, чтобы советник определил?

Вообще, то что мне нужно, следующее:
kLots = величина последней стоповой сделки * коэффициент валюты / тейк профит (в пипсах)

Не поможете с этим?
Заранее благодарен.

OrderStopLoss( ) Возвращает значение цены закрытия позиции при достижении уровня убыточности (stop loss) для текущего выбранного ордера.

Вот индикатор, он сигналит при закрытии ордера и показывает по какому стопу ордер закрылся.
PHP код:

//+------------------------------------------------------------------+
//|                                              AlertCloseOrder.mq4 |
//|                               Copyright © 2010, Vladimir Hlystov |
//|                                         http://cmillion.narod.ru |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2010, Vladimir Hlystov"
#property link      "http://cmillion.narod.ru"
#property indicator_chart_window
int Orders;
//+------------------------------------------------------------------+
int start()
  {
   if (
Orders>OrdersTotal()) AlertOrder();
   
Orders=OrdersTotal();
   return(
0);
  }
//+------------------------------------------------------------------+
void AlertOrder()
{
   
string txt;
   
double OCP;
   
int i=OrdersHistoryTotal()-1;
   if(
OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)==true)
   {                                     
      
OCP=OrderClosePrice();
      if (
OCP==OrderStopLoss()  ) txt="SL";
      if (
OCP==OrderTakeProfit()) txt="TP";
      
Alert("Ордер N ",OrderTicket()," закрыт по ",txt," ",
      
DoubleToStr(OCP,Digits)," прибыль ",DoubleToStr(OrderProfit(),2));
}  }
//+------------------------------------------------------------------+ 

Если добавить в него пару строк, то получится то, что Вам нужно.
Удачи!

machzelet 02.05.2010 20:57

Ой, плин, торможу!
Мне нужно именно то, что просит девушка в первом посте, только не сумма лоссов, а после каждой сделки, закрытой по лосю, чтоб высчитывался лот, необходимый для покрытия лося. Профит у мну тоже стабильный.

machzelet 02.05.2010 23:41

cmillion,
Можете, пожалуйста, глянуть, что я не так делаю? Уже голову сломал над этим кодом ((
Цель - после закрытия ордера по стоп-лоссу, открылся ордер с увеличенным лотом в противоположную сторону, а в сторону стоп-лосса открылся ордер с нормальным лотом.
Что-то код совсем не хочет признавать ордера закрывшиеся по стоп-лоссу.
Заранее благодарю.
С уважением, Евгений.

cmillion 03.05.2010 08:39

Цитата:

Сообщение от machzelet (Сообщение 102937)
cmillion,
Можете, пожалуйста, глянуть, что я не так делаю? Уже голову сломал над этим кодом ((
Цель - после закрытия ордера по стоп-лоссу, открылся ордер с увеличенным лотом в противоположную сторону, а в сторону стоп-лосса открылся ордер с нормальным лотом.
Что-то код совсем не хочет признавать ордера закрывшиеся по стоп-лоссу.
Заранее благодарю.
С уважением, Евгений.

Мне к сожалению некогда посмотреть, но Вы можете посмотреть мои советники, например _http://codebase.mql4.com/ru/6341 Советник из 10 строк "Неваляшка" В нем Вы возможно найти ответ на свой вопрос.
Если не найдете, пишите [Ссылки могут видеть только зарегистрированные пользователи. Зарегистрироваться...]


Удачи!

ale002 03.05.2010 11:09

machzelet, попробуйте эту функцию использовать


Код:

int GetChainLength (int iMagicNumber = 0, int iOrderType = -1, string sSymbol = "", bool bSkipOne = false) {
        //        Функция определяет длину серии закрытых с прибылью (или убытком) ордеров в истории (начиная с последнего по времени)
        //        Если iOrderType = OP_BUY - считаем ордера на покупку
        //        Если iOrderType = OP_SELL - считаем ордера на продажу
        //        Если iOrderType = -1 или не указан вообще - считаем серию независимо от направления ордера
        //        Если iOrderType = 2 - смотрим тип последнего закрытого ордера, т.е. если последний был ордером на продажу - считаем ордера на продажу и наоборот
        //                Если это серия прибыльных ордеров - функция возвращает положительное число, для убыточных - отрицательное
        int
                iChainLength = 0, // счётчик серии
                iProfit = 0 // переменная для определения прибыльная это или убыточная серия
        ;
        for(int iOrder = OrdersHistoryTotal(); iOrder > 0; iOrder--) { // пробег по истории от последнего (по времени закрытия) к первому
                if(OrderSelect(iOrder, SELECT_BY_POS, MODE_HISTORY)) {
                        if(
                                (sSymbol == "" || OrderSymbol() == sSymbol) // если пара не задана или совпадает с искомой
                                && (iMagicNumber == 0 || OrderMagicNumber() == iMagicNumber) // и мэджик не задан или совпадает с искомым
                                && OrderType() < 2 // и это был ордер BUY или SELL
                        ) {
                                if(iOrderType == 2) iOrderType = OrderType(); // если тип ордеров = "по последнему" - дальше будем считать, что ищем именно этот тип ордеров
                                if(!bSkipOne) { // если пропускать этот ордер не нужно
                                        if(iProfit == 0) { // если это первый ордер серии - определим прибыльна она или убыточна
                                                if(OrderProfit() < 0) iProfit = -1; // серия убыточна
                                                else iProfit = 1; // серия не убыточна
                                        }
                                        if(
                                                (iOrderType == -1 || iOrderType == OrderType()) // это тот тип ордеров, которые считаем
                                                && ( // и это тот тип прибыли или убытка, которые считаем
                                                        (OrderProfit() < 0 && iProfit < 0)
                                                        || (OrderProfit() >= 0 && iProfit > 0)
                                                )) {
                                                        iChainLength += iProfit; // увеличим (для убыточной серии) или уменьшим (для прибыльной) счётчик серии
                                                }
                                        else return(iChainLength); // если не совпала прибыльность или тип ордера - значит серия закончилась, заканчиваем и подсчёт, возвращаем результат
                                }
                                else bSkipOne = false; // следующий пропускать не нужно
                        }
                }
        }
        // если работа функции дошла до этой строки - история закончилась
        return(iChainLength); // возвращаем счётчик
}

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

Код:

dLotVolume = glo.dFixedLots;
if(glo.sProfitFactor != "" || glo.sLossFactor != "") { // если заданы множители лотов для прибыльных или убыточных серий
iChainLength = GetChainLength(glo.iMagicNumber); // посчитаем длину серии закрытых ордеров
if(iChainLength > 0 && iChainLength < ArraySize(glo.adProfitFactor)) dLotVolume = glo.dFixedLots * glo.adProfitFactor[iChainLength - 1]; // лот с учётом длины серии прибыльных сделок
if(iChainLength < 0 && -iChainLength < ArraySize(glo.adLossFactor)) dLotVolume = glo.dFixedLots * glo.adLossFactor[-iChainLength - 1]; // лот с учётом длины серии убыточных сделок
}
dLotVolume = GetLotVolume(sSymbol, dLotVolume); // уточним допустимый размер лота

GetLotVolume - это др функция, котор приводит рассчитанный лот в соотв с требованиями брокера. В вашем советнике её сильно упрощённый аналог - CalculateMM()

machzelet 03.05.2010 14:11

ale002, спасибо... но мне нужно нечто иное.
Меня интересует функция, проверяющая последний закрывшийся ордер. И если последний ордер закрыт по стоп-лоссу, то выполняются действия Х. Если последний ордер закрыт по профиту, то выполняются действия У.
Довольно просто, но почему-то у мну не получается вызвать функцию последнего закрывшегося ордера.

double OCP;
int i=OrdersTotal()-1;
if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)==true )
{
OCP=OrderClosePrice();
if (OCP==OrderStopLoss()) k=x*y;
if (OCP==OrderTakeProfit()) k=x/y;

В таком виде советник не желает принимать функцию, он просто напросто не предпринимает никаких действий.

Вот и хотелось бы подсказки, что я делаю не так.

cmillion 03.05.2010 14:34

Цитата:

Сообщение от machzelet (Сообщение 103226)
ale002, спасибо... но мне нужно нечто иное.
Меня интересует функция, проверяющая последний закрывшийся ордер. И если последний ордер закрыт по стоп-лоссу, то выполняются действия Х. Если последний ордер закрыт по профиту, то выполняются действия У.
Довольно просто, но почему-то у мну не получается вызвать функцию последнего закрывшегося ордера.

double OCP;
int i=OrdersTotal()-1;
if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)==true )
{
OCP=OrderClosePrice();
if (OCP==OrderStopLoss()) k=x*y;
if (OCP==OrderTakeProfit()) k=x/y;

В таком виде советник не желает принимать функцию, он просто напросто не предпринимает никаких действий.

Вот и хотелось бы подсказки, что я делаю не так.

Для вызова этой функции, Вам необходимо определить, что ордер закрылся. Например так:
PHP код:

int Orders;
//+------------------------------------------------------------------+
int start()
  {
   if (
Orders>OrdersTotal()) ВАША_ФУНКЦИЯ();
   
Orders=OrdersTotal();
   return(
0);
  } 


machzelet 03.05.2010 20:41

Вот кусок кода, где идет сравнение - закрылся ордер по профиту или по стоп-лоссу. Далее идет переход к функции set_kLots_sell или set_kLots_buy, если сравнение верно.

Код:

for (int i=OrdersTotal()-1; i>=0; i--)
      {
      if (OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)==false) break;
      if (OrderSymbol()!=Symbol()) continue;
      if (OrderType()!=OP_BUY && OrderType()!=OP_SELL) continue;
      if (OrderProfit()>0) continue;
        {
        OCP=OrderClosePrice();
        if (OrderType()==OP_BUY)
            { if (OCP==OrderStopLoss()) set_kLots_sell=1; }
        if (OrderType()==OP_SELL)
            { if (OCP==OrderStopLoss()) set_kLots_buy =1; }
        }
      }

Или так тоже пробовал...

Код:

for (int i=OrdersTotal()-1; i>=0; i--)
      {
      if (OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)==false) break;
      if (OrderSymbol()!=Symbol()) continue;
      if (OrderType()!=OP_BUY && OrderType()!=OP_SELL) continue;
      if (OrderProfit()>0) continue;
        {
        if (OrderType()==OP_BUY) set_kLots_sell=1;
        if (OrderType()==OP_SELL) set_kLots_buy =1;
        }
      }

Но ни так ни сяк не выходит. Знаю, что мну сейчас закидают шапками и помидорами, но я чайник и только учусь. Очень надеюсь на вашу помощь.

cmillion 03.05.2010 21:03

Цитата:

Сообщение от machzelet (Сообщение 103453)
Но ни так ни сяк не выходит.

PHP код:

int Orders;
//+------------------------------------------------------------------+
int start()
  {
   
string tip;
   if (
Orders>OrdersTotal()) tip=LastOrder();
   
Orders=OrdersTotal();
   if (
tip=="SL")
   {
      
Comment("Ордер закрылся по SL");
   }
   if (
tip=="TP")
   {
      
Comment("Ордер закрылся по TP");
   }
   return(
0);
  }
//+------------------------------------------------------------------+
string LastOrder()
{
   
double OCP;
   
int i=OrdersHistoryTotal()-1;
   if(
OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)==true)
   {                                     
      
OCP=OrderClosePrice();
      if (
OCP==OrderStopLoss()  ) return("SL");
      if (
OCP==OrderTakeProfit()) return("TP");
   }  
   return(
"");
}
//+------------------------------------------------------------------+ 


machzelet 04.05.2010 16:05

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

Код:

extern int StartHour=15;              // Время открытия ордеров
extern int TimeZone=0;                // Временная зона
extern int OrderExpirationDays=3;      // Срок жизни ордера в днях, если он не закрылся по стопу или профиту
extern int TakeProfit=14;              // Желаемая прибыль
extern int CurrencyFactor=37;          // Валютный коэффициент
extern double Lots=0.01;              // Величина лота
extern double RiskPercentLoss=30;      // Процент максимального убытка от депозита на один ордер
extern bool RiskMM=true;              // Мани Менеджмент
extern double RiskPercentMM=10;        // Процент риска


int set_buy=0;
int set_sell=0;
int StopLoss, LotFactor;
double kLots;

void start()
  {
  if (Bars<100 || IsTradeAllowed()==false) return;
  if (TimeZone<-23 || TimeZone>23) return;
  TestOrderExpirationDays();
  int hour=Hour()-TimeZone;
  if (DayOfWeek()>=1 && DayOfWeek()<=5 && hour==StartHour)
      {
      if (set_buy==0 && TotalBuy()==0) { if (OpenBuy()>0) {set_buy=1; return;} }
      if (set_sell==0 && TotalSell()==0) { if (OpenSell()>0) {set_sell=1; return;} }
      }
  else
      {
      set_buy=0;
      set_sell=0;
      }
  }

void TestOrderExpirationDays()
  { 
  if(RiskMM)CalculateMM(); 
  int set_double_buy =0;
  int set_double_sell=0;
  int ticket, slippage;
  double loss, profit;
 
  for (int i=OrdersTotal()-1; i>=0; i--)
      {
      if (OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) break;
      if (OrderSymbol()!=Symbol()) continue;
      if (OrderType()!=OP_BUY && OrderType()!=OP_SELL) continue;
      if (CurTime()-OrderOpenTime()<=86400*OrderExpirationDays) continue;
        {
        if (OrderType()==OP_BUY )
            { if (OrderClose(OrderTicket(),OrderLots(),Bid,slippage)) set_double_buy=1; }
        if (OrderType()==OP_SELL)
            { if (OrderClose(OrderTicket(),OrderLots(),Ask,slippage)) set_double_sell=1; }
        }

      }
     
      kLots=(Lots*RiskPercentMM)/3;
      LotFactor=Lots*100;
      StopLoss=(AccountBalance()*RiskPercentLoss)/(CurrencyFactor*LotFactor);
   

   
     
  if (set_double_buy>0)
      {
      slippage=2;
      loss=0; if (StopLoss>0) loss=Ask-StopLoss*Point;
      profit=0; if (TakeProfit>0) profit=Ask+TakeProfit*Point;
      ticket=OrderSend(Symbol(),OP_BUY,kLots*Lots,Ask,slippage,loss,profit,"",0,0);
      if (ticket>0) set_buy=0;
      else Print("Open a order failed with error #",GetLastError());
      }
  if (set_double_sell>0)
      {
      slippage=2;
      loss=0; if (StopLoss>0) loss=Bid+StopLoss*Point;
      profit=0; if (TakeProfit>0) profit=Bid-TakeProfit*Point;
      ticket=OrderSend(Symbol(),OP_SELL,kLots*Lots,Bid,slippage,loss,profit,"",0,0);
      if (ticket>0) set_sell=0;
      else Print("Open a order failed with error #",GetLastError());
      }

  }

  int OpenBuy()
  {
  int slippage=2;
  double loss=0; if (StopLoss>0) loss=Ask-StopLoss*Point;
  double profit=0; if (TakeProfit>0) profit=Ask+TakeProfit*Point;
  int ticket=OrderSend(Symbol(),OP_BUY,Lots,Ask,slippage,loss,profit,"",0,0);
  if (ticket==0) Print("Open a order failed with error #",GetLastError());
  return (ticket);
  }

  int OpenSell()
  {
  int slippage=2;
  double loss=0; if (StopLoss>0) loss=Bid+StopLoss*Point;
  double profit=0; if (TakeProfit>0) profit=Bid-TakeProfit*Point;
  int ticket=OrderSend(Symbol(),OP_SELL,Lots,Bid,slippage,loss,profit,"",0,0);
  if (ticket==0) Print("Open a order failed with error #",GetLastError());
  return (ticket);
  }

  int TotalBuy()
  {
  int count=0;
  for (int i=0; i<OrdersTotal(); i++)
      {
      if (OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) break;
      if (OrderSymbol()==Symbol() && OrderType()==OP_BUY) count++;
      }
  return (count);
  }

  int TotalSell()
  {
  int count=0;
  for (int i=0; i<OrdersTotal(); i++)
      {
      if (OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) break;
      if (OrderSymbol()==Symbol() && OrderType()==OP_SELL) count++;
      }
  return (count);
  }



//+------------------------------------------------------------------+
//| Money Management                                                |
//+------------------------------------------------------------------+

void CalculateMM()
{
  double MinLots=MarketInfo(Symbol(),MODE_MINLOT);
  double MaxLots=MarketInfo(Symbol(),MODE_MAXLOT);
  Lots=AccountFreeMargin()/100000*RiskPercentMM;
  Lots=MathMin(MaxLots,MathMax(MinLots,Lots));
  if(MinLots<0.1)Lots=NormalizeDouble(Lots,2);
  else
  {
    if(MinLots<1)Lots=NormalizeDouble(Lots,1);
    else Lots=NormalizeDouble(Lots,0);
  }
  if(Lots<MinLots)Lots=MinLots;
  if(Lots>MaxLots)Lots=MaxLots;
  return(0);
}

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

Красным выделен кусок, который проверяет время открытия ордера и по истечении 3 дней закрывает его, если тот не закрылся по профиту. После чего переходит к куску кода синего цвета.

Моя цель - заменить красный кусок кода на проверку закрытия ордера по стоп-лоссу, и если ордер действительно закрылся по стоп-лоссу, а не по профиту, тогда перейти к куску кода синего цвета.

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

Помогите, плиз, домучать.

cmillion 04.05.2010 18:55

Цитата:

Сообщение от machzelet (Сообщение 103880)
Ребят, простите, но "моя твоя не понимать". ((
Помогите, плиз, домучать.

У Вас принципиально не правильная постановка задачи.
Если Вы хотите при закрытии ордера открывать ордер в ту или иную сторону, в зависимости от закрытия по СЛ или ТП, то Вам не надо закрывать ордера принудительно по времени, т.к. они будут закрыты по текушей цене, а не по стопам.
Далее, если Вы все же закрываете ордера принудительно, то необходимо определить с прибылью или с убытком они закрылись и от этого назначать переменным set_double_buy и set_double_sell их значения. Например:
PHP код:

if (OrderType()==OP_BUY )
{
   if (
OrderProfit()>0set_double_buy=1
   else 
set_double_buy=0;
   
OrderClose(OrderTicket(),OrderLots(),Bid,slippage)


Если Вы все же хотите анализировать уже закрытые ордера, то воспользуйтесь текстом программы из моего предыдущего поста.
Удачи!


Текущее время: 01:44. Часовой пояс GMT.

Перевод: zCarot
Copyright ©2000 - 2018, Jelsoft Enterprises Ltd.
SEO by vBSEO