У кого-нить функция вычисления баланса и profit/loss по неделям с учётом пополнений/снятий ?
Понадобилось вот, но перед тем как писать лучше поспрашивать - такое 100500 раз должно быть уже написано
Раз ни у кого нет или все супер-жадные пришлось написать.
В деталях не отлажено, но работает, можете пользоваться. Если какие идеи, замечания - пишите
//+------------------------------------------------------------------+ //| BalanceAndPL.mqh | //| Copyright 2018, MaximKuznetsov | //| https://www.luxtrade.tk | //+------------------------------------------------------------------+ #property copyright "Copyright 2018,Maxim Kuznetsov" #property link "https://www.luxtrade.tk" #property strict /** отчётная периодичность **/ enum ENUM_TIME_PERIODIC { MODE_DAILY, /// ежедневно MODE_WEEKLY, /// еженедельно. с понедельника по воскресенье. MODE_MONTHLY /// ежемесячно }; /** Вычисление баланса и зафиксированной прибыли на начало периода @arg mode выбор перода (см. ENUM_TIME_PERIODIC) @arg count кол-во периодов для рассчёта @arg balance массив для сохранения балансов @arg pl массив для заполнения profit/loss @return int 0 при успешном завершениее иначе код ошибки **/ int BalanceAndPL(ENUM_TIME_PERIODIC mode,int count,double &balance[],double &pl[]) { // проверка аргументов if (count<0) { return -1; } if (ArraySize(balance)<count && !ArrayResize(balance,count)) { return -1; } if (ArraySize(pl)<count && !ArrayResize(pl,count)) { return -1; } // вычисление времени начала периодов datetime period[]; if (!ArrayResize(period,count)) { return -1; } datetime now=TimeCurrent(); switch (mode) { case MODE_DAILY: { MqlDateTime dt; if (!TimeToStruct(now,dt)) { return -1; } dt.sec=0; dt.min=0; dt.hour=0; period[0]=StructToTime(dt); for(int t=1;t<count;t++) { period[t]=period[t-1]-24*60*60; } } break; case MODE_WEEKLY: { MqlDateTime dt; if (!TimeToStruct(now,dt)) { return -1; } dt.sec=0; dt.min=0; dt.hour=0; period[0]=StructToTime(dt)-((dt.day_of_week+6)%7)*24*60*60; for(int t=1;t<count;t++) { period[t]=period[t-1]-7*24*60*60; } } break; case MODE_MONTHLY: { MqlDateTime dt; if (!TimeToStruct(now,dt)) { return -1; } dt.day=1; dt.sec=0; dt.min=0; dt.hour=0; period[0]=StructToTime(dt); for(int t=1;t<count;t++) { dt.mon--; if (dt.mon==0) { dt.mon=12; dt.year--; } period[t]=StructToTime(dt); } } break; } int curr=0; // текущий период balance[curr]=AccountBalance(); pl[curr]=0; for(int pos=OrdersHistoryTotal()-1;pos>=0 ;pos--) { if (!OrderSelect(pos,SELECT_BY_POS,MODE_HISTORY)) { continue; } int type=OrderType(); if (type==OP_BUY || type==OP_BUYLIMIT || type==OP_BUYSTOP || type==OP_SELL || type==OP_SELLLIMIT || type==OP_SELLSTOP) { // ордер // ориентируемся по времени закрытия datetime orderTime=OrderCloseTime(); if (orderTime<period[curr]) { // ордер относится к какому-то пред.периоду do { curr++; if (curr==count) { // все периоды посчитаны break; } balance[curr]=balance[curr-1]; pl[curr]=0; } while(orderTime<period[curr]); if (curr==count) break; } if (type==OP_BUY || type==OP_SELL) { double profit=OrderProfit()+OrderSwap()+OrderCommission(); balance[curr]-=profit; pl[curr]+=profit; } } else { // изменения баланса // ориентируемся по времени открытия datetime orderTime=OrderOpenTime(); if (orderTime<period[curr]) { // ордер относится к какому-то пред.периоду do { curr++; if (curr==count) { // все периоды посчитаны break; } balance[curr]=balance[curr-1]; pl[curr]=0; } while(orderTime<period[curr]); if (curr==count) break; } double profit=OrderProfit()+OrderSwap()+OrderCommission(); balance[curr]-=profit; } } // если не все периоды заполнены - заполнить for(curr++;curr<count;curr++) { balance[curr]=balance[curr-1]; pl[curr]=0; } return 0; }
А зачем столько операций сравнения?
if (type==OP_BUY || type==OP_BUYLIMIT || type==OP_BUYSTOP || type==OP_SELL || type==OP_SELLLIMIT || type==OP_SELLSTOP)
Данное выражение всегда true
А вот это:
if (type==OP_BUY || type==OP_SELL)
лучше так писать: if (type<2). Оно вроде при современном быстродействии и не существенно, но, тут лишняя команда процессору, тут две, а потом на медленный тестер жалуемся.
Туда же и вот это:
7*24*60*60
Сложно разве макрос определить?
#define _WEEK 604800
А зачем столько операций сравнения?
Данное выражение всегда true
А вот это:
лучше так писать: if (type<2). Оно вроде при современном быстродействии и не существенно, но, тут лишняя команда процессору, тут две, а потом на медленный тестер жалуемся.
заблуждаетесь в обоих случаях :-)
1. при пополнении/снятии type отличен от типа ордера
2. не стоит опираться на конкретные числовые значения перечислений
заблуждаетесь в обоих случаях :-)
1. при пополнении/снятии type отличен от типа ордера
2. не стоит опираться на конкретные числовые значения перечислений
Виноват, тогда:
if (type<6)
![MQL5 - Язык торговых стратегий для клиентского терминала MetaTrader 5](https://c.mql5.com/i/registerlandings/logo-2.png)
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
У кого-нить функция вычисления баланса и profit/loss по неделям с учётом пополнений/снятий ?
Понадобилось вот, но перед тем как писать лучше поспрашивать - такое 100500 раз должно быть уже написано