for(int i=OrdersHistoryTotal();i>0;i--) { OrderSelect(i,SELECT_BY_POS,MODE_HISTORY);т.к. что-то мне подсказывает, что номера ордеров идут от 0 до N-1, где N - количество ордеров, а вообще у самого давно мысль перебирать историю на предмет убытков для расчета оптимального размера позиции согласно, по моему, книге "математика управления капиталом", только там речь о самой убыточной непрерывной последовательности сделок, а в вашем случае, как я понял, он считает убыток, полученный за последнюю серию и то, только в том случае, если сделка(и) все таки принесла убыток. Если последняя сделка принесла определенную прибыль, то CalcLot() всегда вернет BasicLot.
И еще я не совсем понял больше какой величины должен быть OrderProfit(), что бы проверка сочла сделку прибыльной. Так же не совсем ясна изначальная
постановка задачи: сколькими лотами нужно играть, чтоб при получении X пунктов прибыли компенсировать Y% потерь от убыточных сделок?
З.Ы. Еще бы предложил все таки проверять
if (OrderSelect(...)==true) {...}сами понимаете зачем.
double LotsOptimized(int type) { double Lot; double minLots=MarketInfo(Symbol(),MODE_MINLOT); double maxLots=MarketInfo(Symbol(),MODE_MAXLOT); double tmpLot; int orders = HistoryTotal(); // history orders total int losses = 0; // number of losses orders without a break //---- select lot size int typeOpenOrder; if(MaximumRisk==0) { Lot=Lots; } else if(openCurBuy==0 && openCurSell==0) { freeMarging=AccountFreeMargin()/MaxCurentOrders; Lot = NormalizeDouble(freeMarging*MaximumRisk / (Bid*MathPow(10,Digits-1)), 2); Lots=Lot; } if(type==OP_BUY) { typeOpenOrder =openCurBuy; } if(type==OP_SELL) { typeOpenOrder =openCurSell; } switch(OptimizeType) { case 0: tmpLot=0; break; case 1: tmpLot=typeOpenOrder*Lot; break; case 2: tmpLot=(MaxCurentOrders-typeOpenOrder)*Lot; break; } Lot = Lot+(tmpLot); //---- calcuulate number of losses orders without a break if(DecreaseFactor > 0) { for(int i = orders - 1; i >= 0; i--) { if(OrderSelect(i, SELECT_BY_POS, MODE_HISTORY) == false) { Print("Error in history!"); break; } //---- if(OrderSymbol() != Symbol() || OrderType() > OP_SELL) continue; //---- if(OrderProfit() > 0) break; //---- if(OrderProfit() < 0) losses++; } if(losses > 1) Lot = NormalizeDouble(Lot - Lot*losses / DecreaseFactor, 2); } //---- return lot size if(Lot < minLots ) Lot = minLots; if(MaximumLots != 0 && Lot > MaximumLots ) Lot = MaximumLots; if(Lot > maxLots) Lot = maxLots; return(Lot); }Вот
if(DecreaseFactor > 0) { for(int i = orders - 1; i >= 0; i--) { if(OrderSelect(i, SELECT_BY_POS, MODE_HISTORY) == false) { Print("Error in history!"); break; } //---- if(OrderSymbol() != Symbol() || OrderType() > OP_SELL) continue; //---- if(OrderProfit() > 0) break; //---- if(OrderProfit() < 0) losses++; } if(losses > 1) Lot = NormalizeDouble(Lot - Lot*losses / DecreaseFactor, 2); }как раз то что ты хочешь :-) было в каком то советнике, взял себе на вооружение :-)
Есть идеи как подправить? а то у меня что-то не получается... Расчет потерь вроде работает нормально. Проверял - читает данные истории. Вот только лот неправильный выходит.
Помогите найти ошибку пожалуйста!
По коду вроде должно работать. Может быть дело в каких-то сопутствующих обстоятельствах? Пробовали вставлять перед
double calculatedlot=-Calculate_Loss()*(1+PercentGain/100.0)/Limit/10.0;
Print("",Calculate_Loss()," ",PercentGain," ",Limit);? И, кстати, для цены пункта может лучше отвести переменную.
Добавил строку принта. Выдает что тотал лосс = -6 -3 -5 -10 и другую чепуху.
переписал total_loss=total_loss+OrderProfit()+OrderSwap() но ничего не изменилось
Переписал немного:
double CalcLot() { ///////----------- SHOULD BE -------------- double lot=(PercentGain+TotalLoss)/Limit; ------------------ ///////// // Print("Loss = ",Calculate_Loss()," PercentGain = ",PercentGain," Limit = ",Limit); double total_loss,current_loss; for(int i=OrdersHistoryTotal();i>0;i--) { if (OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)==true) OrderSelect(i,SELECT_BY_POS,MODE_HISTORY); if(OrderProfit()>0)//PipsLoss*OrderLots()*10.0) { break; } else if(OrderProfit()<0) { current_loss=OrderProfit()+OrderSwap(); Print("current_loss = ",current_loss); total_loss=total_loss+current_loss; Print("total_loss = ",total_loss); } } double calculatedlot=0; calculatedlot=-total_loss*(1+PercentGain)/Limit/10.0; Print("-total_loss*(1+PercentGain) = ",-total_loss*(1+PercentGain)); double lot=NormalizeDouble(calculatedlot,2); if(lot<BasicLot) lot=BasicLot; if(AccountBalance()<lot*100) return(BasicLot); return(lot); }Теперь почти пашет. Но мне нужно округление вверх. Как такое посчитать?
При переносе из одной функции в другую похоже перекидывалось значение без запятой...
Вам сразу дали дельный совет, которым я настоятельно рекомендую всё-таки воспользоваться:
Bones 20.06.2007 05:50
for(int i=OrdersHistoryTotal();i>0;i--) { OrderSelect(i,SELECT_BY_POS,MODE_HISTORY);т.к. что-то мне подсказывает, что номера ордеров идут от 0 до N-1 ... (конец цитаты)
for(int i=0; i<OrdersHistoryTotal(); i++)
if(AccountBalance()<lot*100) return(BasicLot); return(lot); }
Посмотрел хелпер, для OrderSelect пример не о особо наглядный. Так что фиг с ней, с педагогикой :) , вот вариант кода, если он не будет работать убедитесь, что до обращения к функции с PercentGain и Limit ничего не происходит
double CalcLot() { ///////----------- SHOULD BE -------------- double lot=(PercentGain+TotalLoss)/Limit; ------------------ ///////// double current_loss; double total_loss = 0; for(int i=0;i<OrdersHistoryTotal();i++) { if (OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)==true) { if(OrderProfit()>0)//PipsLoss*OrderLots()*10.0) { continue; } else if(OrderProfit()<0) { current_loss=OrderProfit()+OrderSwap(); Print("current_loss = ",current_loss); total_loss=total_loss+current_loss; Print("total_loss = ",total_loss); } } else { Print("OrderSelect() вернул ошибку - ",GetLastError()); return(-1); } } double calculatedlot=0; // Print("Loss = ",Calculate_Loss()," PercentGain = ",PercentGain," Limit = ",Limit); calculatedlot=-total_loss*(1+PercentGain)/Limit/10.0; Print("-total_loss*(1+PercentGain) = ",-total_loss*(1+PercentGain)); double lot=NormalizeDouble(calculatedlot,2); if(lot<BasicLot) lot=BasicLot; if(AccountBalance()<lot*100) return(BasicLot); else return(lot); }
Насчёт округления всегда в большую сторону можно попробовать умножить на 100, применить MathCeil и поделить обратно.
Сделал в коде маленькую поправку (заменил break на continue) :)
вот нашел проблемку. если сделать
calculatedlot=-total_loss*(1+PercentGain)/Limit/(Bid*1000/AccountBalance());то пашет для фунта. но не пашел для евро - слишком сильно растет лот...
Тогда нужно for(int i=OrdersHistoryTotal()-1;i>=0;i--) Ну и вроде действительно break вернуть надо. В общем-то мне гораздо быстрее отладить код самому, но для отладки этого нюанса нужно довольно упорно создавать нужную ситуацию в истории ордеров :)
Насчёт последней новации - это что - так цена пункта считается?
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
Интересует такой вопрос: кто-то уже научился считать лоты экспертом, добавляя в размер лота только значение потерь? а если потери составляют 0 то и размер лота ставим по дефолту.
Пробовал искать - не нашел
Вот код, который я использую. Работает на евро-доллар для limit = 100. не работает на паре фунт-доллар с лимитом 12. Лимит = тейкпрофит.
При вызывается посылкой на CalcLot();
PercentGain = уровень потерь, которые мы хотим компенсировать сделующим ордером + 100%
Limit = TakeProfit.
BasicLot = 0.1 или 0.01
Пример:
2 лося. 0.05 бакса и 0.08 бакса
0.05 + 0.08 = 0.13
0.13 * 100% (PercentGain) = 0.26
0.26 / 12 = 0.216 (округлить вверх до 0.03)Есть идеи как подправить? а то у меня что-то не получается... Расчет потерь вроде работает нормально. Проверял - читает данные истории. Вот только лот неправильный выходит.
Помогите найти ошибку пожалуйста!