Как рассчитать размер комиссии брокера в пунктах? - страница 4

 

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

Вот выловил разброс на 4 пипса:

Тест 03

Вот на 5:

04

 
Yury Kirillov:

И Вы не хотите повысить точность расчетов на 3 пипса? Для Вас такая погрешность не важна?

Зачем, что это принесёт? Попробуйте использовать для своей прямой задачи стандартную функцию, и свою, вы вообще не увидите разницы, это всё забубоны.

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

 

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

Результаты приведены на скриншоте внизу.

Было произведено 1000 потиковых прогонов для 14 валютных пар.

Подсчитывались:

1. Суммарное отклонение значений.

2. Суммарное абсолютное (по модулю) отклонение значений.

3. Среднее отклонение значений (суммарное отклонение/число прогонов).

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

1. Суммарное отклонение значений: EURTRY +0.20460 GBPNZD -0.08996 EURNZD -0.07415

2. Суммарное абсолютное (по модулю) отклонение значений: EURTRY +101.81853 GBPNZD 48.22592 EURNZD 38.70629

3. Среднее отклонение значений (суммарное отклонение/число прогонов): EURTRY +0.00020 GBPNZD -0.00009 EURNZD -0.00007

Советник примененный для тестирования:

//+------------------------------------------------------------------+
//|                                  SymbolData Tick Value Test Mini |
//|                                         KirillovYV (c) 2013-2017 |
//|                         https://www.mql5.com/ru/users/kirillovyv |
//+------------------------------------------------------------------+
#property copyright "KirillovYV (c) 2013-2017"
#property link      "https://www.mql5.com/ru/users/kirillovyv"
#property version   "1.11"
#property strict
double   TVStd=0.0;
double   TVCalc=0.0;
double   dTV=0.0;
int      nTick=0;
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnTick(){
   nTick++;
   Print(nTick);
   TVStd=TVStd+MarketInfo(_Symbol,MODE_TICKVALUE);
   TVCalc=TVCalc+CalcTickValue(_Symbol,2);
   dTV=dTV+MathAbs(TVStd-TVCalc);
   Comment("=============== Reference data on the instrument "+_Symbol+" ============================="
   +"\n\n ================================== BID ==================================="
   +"\n\n Среднее (",IntegerToString(nTick)," прогонов) TICKVALUE (MarketInfo(_Symbol,MODE_TICKVALUE))="+DoubleToString(TVStd/nTick,_Digits)
   +"\n\n Среднее (",IntegerToString(nTick)," прогонов) TICKVALUE (расчетное)="+DoubleToString(TVCalc/nTick,_Digits)
   +"\n\n Суммарное отклонение (",IntegerToString(nTick)," прогонов)="+DoubleToString((TVStd-TVCalc),_Digits)
   +"\n\n Суммарное накопленное отклонение (",IntegerToString(nTick)," прогонов)="+DoubleToString(dTV,_Digits)
   +"\n\n Среднее отклонение (",IntegerToString(nTick)," прогонов)="+DoubleToString((TVStd-TVCalc)/nTick,_Digits)
   +"\n\n ======================================================================="
   );
   {if(nTick>=1000)
   {
      ExpertRemove();
   }}//if(nTick>=1000)
}
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnDeinit(const int reason){
Comment("=============== Reference data on the instrument "+_Symbol+" ============================="
+"\n\n ================================== BID ==================================="
+"\n\n Среднее (1000 прогонов) TICKVALUE (MarketInfo(_Symbol,MODE_TICKVALUE))="+DoubleToString(TVStd/1000,_Digits)
+"\n\n Среднее (1000 прогонов) TICKVALUE (расчетное)="+DoubleToString(TVCalc/1000,_Digits)
+"\n\n Суммарное отклонение (1000 прогонов)="+DoubleToString((TVStd-TVCalc),_Digits)
+"\n\n Суммарное накопленное отклонение (1000 прогонов)="+DoubleToString(dTV,_Digits)
+"\n\n Среднее отклонение (1000 прогонов)="+DoubleToString((TVStd-TVCalc)/1000,_Digits)
+"\n\n ======================================================================="
);
//Comment("=============== Reference data on the instrument "+"EURCHF"+" ============================="
////+"\n\n TICKVALUE (CalcTickValue(_Symbol,Mid))="+DoubleToString(CalcTickValue("EURCHF",0),_Digits)
//+"\n\n ================================== ASK ==================================="
//+"\n\n SymbolInfoDouble('EURCHF',SYMBOL_ASK)="+DoubleToString(SymbolInfoDouble("EURCHF",SYMBOL_ASK),_Digits)
//+"\n\n SymbolInfoDouble('EURUSD',SYMBOL_ASK)="+DoubleToString(SymbolInfoDouble("EURUSD",SYMBOL_ASK),_Digits)
//+"\n\n TICKVALUE (CalcTickValue(_Symbol,Ask))="+DoubleToString(CalcTickValue("EURCHF",1),_Digits)
//+"\n\n TICKVALUE = объем позиции * размер пункта * текущая котировка базовой валюты по отношению к USD / текущий курс валютной пары (кросс-курс)"
//+"\n\n TICKVALUE(ASK)="+DoubleToString(SymbolInfoDouble("EURCHF",SYMBOL_TRADE_CONTRACT_SIZE),2)
//                      +"*"
//                      +DoubleToString(SymbolInfoDouble("EURCHF",SYMBOL_POINT),_Digits)
//                      +"*"
//                      +DoubleToString(SymbolInfoDouble("EURUSD",SYMBOL_ASK),_Digits)
//                      +"/"
//                      +DoubleToString(SymbolInfoDouble("EURCHF",SYMBOL_ASK),_Digits)
//+"\n\n TICKVALUE(ASK)="+DoubleToString(SymbolInfoDouble("EURCHF",SYMBOL_TRADE_CONTRACT_SIZE)*SymbolInfoDouble("EURCHF",SYMBOL_POINT)*SymbolInfoDouble("EURUSD",SYMBOL_ASK)/SymbolInfoDouble("EURCHF",SYMBOL_ASK),_Digits)
//+"\n\n TICKVALUE (MarketInfo(_Symbol,MODE_TICKVALUE))="+DoubleToString(MarketInfo("EURCHF",MODE_TICKVALUE),_Digits)
//+"\n\n TICKVALUE (SymbolInfoDouble(_Symbol(),SYMBOL_TRADE_TICK_VALUE))="+DoubleToString(SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_VALUE),_Digits)
//+"\n\n ================================== BID ==================================="
//+"\n\n SymbolInfoDouble('EURCHF',SYMBOL_BID)="+DoubleToString(SymbolInfoDouble("EURCHF",SYMBOL_BID),_Digits)
//+"\n\n SymbolInfoDouble('EURUSD',SYMBOL_BID)="+DoubleToString(SymbolInfoDouble("EURUSD",SYMBOL_BID),_Digits)
//+"\n\n TICKVALUE (CalcTickValue(_Symbol,Bid))="+DoubleToString(CalcTickValue("EURCHF",2),_Digits)
//+"\n\n TICKVALUE = объем позиции * размер пункта * текущая котировка базовой валюты по отношению к USD / текущий курс валютной пары (кросс-курс)"
//+"\n\n TICKVALUE(BID)="+DoubleToString(SymbolInfoDouble("EURCHF",SYMBOL_TRADE_CONTRACT_SIZE),2)
//                      +"*"
//                      +DoubleToString(SymbolInfoDouble("EURCHF",SYMBOL_POINT),_Digits)
//                      +"*"
//                      +DoubleToString(SymbolInfoDouble("EURUSD",SYMBOL_BID),_Digits)
//                      +"/"
//                      +DoubleToString(SymbolInfoDouble("EURCHF",SYMBOL_BID),_Digits)
//+"\n\n TICKVALUE(BID)="+DoubleToString(SymbolInfoDouble("EURCHF",SYMBOL_TRADE_CONTRACT_SIZE)*SymbolInfoDouble("EURCHF",SYMBOL_POINT)*SymbolInfoDouble("EURUSD",SYMBOL_BID)/SymbolInfoDouble("EURCHF",SYMBOL_BID),_Digits)
//+"\n\n TICKVALUE (MarketInfo(_Symbol,MODE_TICKVALUE))="+DoubleToString(MarketInfo("EURCHF",MODE_TICKVALUE),_Digits)
//+"\n\n TICKVALUE (SymbolInfoDouble(_Symbol(),SYMBOL_TRADE_TICK_VALUE))="+DoubleToString(SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_VALUE),_Digits)
//+"\n\n ======================================================================="
//);
//Comment("=============== Reference data on the instrument "+_Symbol+" ============================="
//+"\n\n TICKVALUE (MarketInfo(_Symbol,MODE_TICKVALUE))="+DoubleToString(MarketInfo(_Symbol,MODE_TICKVALUE),_Digits)
//+"\n\n TICKVALUE (SymbolInfoDouble(_Symbol(),SYMBOL_TRADE_TICK_VALUE))="+DoubleToString(SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_VALUE),_Digits)
//+"\n\n TICKVALUE (CalcTickValue(_Symbol,Mid))="+DoubleToString(CalcTickValue(_Symbol,0),_Digits)
//+"\n\n TICKVALUE (CalcTickValue(_Symbol,Ask))="+DoubleToString(CalcTickValue(_Symbol,1),_Digits)
//+"\n\n TICKVALUE (CalcTickValue(_Symbol,Bid))="+DoubleToString(CalcTickValue(_Symbol,2),_Digits)
//+"\n\n ======================================================================="
//);
}//OnStart()
//
//======================================================================================================
//    CalcTickValue()  - вычисляет стоимость пункта для указанного инструмента
//    Вход:
//       iSymbol  -  используемый инструмент (валютная пара)
//    Выход:
//       double   -  расчетная стоимость
//======================================================================================================
double CalcTickValue(string iSymbol, int iMode){
//double CalcTickValue(string iSymbol, double iNPoint, double iLots){SYMBOL_TRADE_CONTRACT_SIZE
string
   iPairs=
      //Прямые
      "#AUD"+"%0"//AUDUSD
      "#EUR"+"%0"//EURUSD
      "#GBP"+"%0"//GBPUSD
      "#NZD"+"%0"//NZDUSD

      "#XAU"+"%0"//GBPUSD
      "#XAG"+"%0"//XAGUSD
      "#XPT"+"%0"//XPTUSD
      "#XPD"+"%0"//XPDUSD
      "#GLD"+"%0"//GLDUSD

      "#LTC"+"%0"//LTCUSD
      "#BTC"+"%0"//BTCUSD
      
      "#USOil"+"%0"//USOUSD
      "#UKOil"+"%0"//UKOUSD

      "#USD"+"%0"//
      //Обратные
      "#CAD"+"%1"//USDCAD
      "#CHF"+"%1"//USDCHF
      "#JPY"+"%1"//USDJPY
      "#NOK"+"%1"//USDNOK
      "#SEK"+"%1"//USDSEK
      "#HKD"+"%1"//USDHKD
      "#CNH"+"%1"//USDCNH
      "#MXN"+"%1"//USDMXN
      "#PLN"+"%1"//USDPLN
      "#TRY"+"%1"//USDTRY
      "#ZAR"+"%1"//USDZAR
      "#RUB"+"%1"//USDRUB
      ;
string
   BaseCurrency=StringSubstr(iSymbol,0,3),
   CotirCurrency=StringSubstr(iSymbol,3,3),
   OilCurrency=StringSubstr(iSymbol,2,3);//не доделано
double
   ContractSize=SymbolInfoDouble(iSymbol,SYMBOL_TRADE_CONTRACT_SIZE);
double
   sPoint=SymbolInfoDouble(iSymbol,SYMBOL_POINT);
//-----   
   {if(BaseCurrency=="USD")//USDZZZ - Прямая котировка, Базовая валюта доллар США, стоимость лота $ContractSize
   {
      /*Расчет стоимости пункта в прямых котировках
      В прямых котировках мы совершаем операции с долларом, а «оплачиваем» второй валютой. 
      Для примера возьмем USD/CHF. Предположим, что ее текущее значение 1.20000. Рассчитаем цену пункта для операции объемом 100 000 (1 лот) базовой валюты. 
      Исходя из текущего курса: 100 000 USD = 120 000 CHF.
      Предположим, что цена прошла в нужном нам направлении 1 пункт, и текущий курс составил 1.20001. 100 000 долларов в данном случае уже будет стоить 120 001 франков. 
      Следовательно, мы заработали 1 швейцарский франк. Теперь нужно перевести это значение в американские доллары. 
      Для этого нужно разделить прибыль на текущий курс: 1 / 1.20001 = 0,83 $. Это и есть цена одного пункта по паре USD/CHF.
      Формула расчета: Цена пункта = объем позиции * размер пункта / текущий курс
      Для разобранного выше примера по паре USD/CHF: 100 000 (объем позиции) * 0,00001 (один пункт) / 1,20001 (текущий курс) = 0,83 $.*/
      {switch(iMode)
      {
            case 0://Mid
               {
                  return(ContractSize*sPoint/((SymbolInfoDouble(iSymbol,SYMBOL_ASK)+SymbolInfoDouble(iSymbol,SYMBOL_BID))/2.0));
               }
            case 1://Ask
               {
                  return(ContractSize*sPoint/SymbolInfoDouble(iSymbol,SYMBOL_ASK));
               }
            case 2://Bid
               {
                  return(ContractSize*sPoint/SymbolInfoDouble(iSymbol,SYMBOL_BID));
               }
      }}//switch(iMode)
   }else{//if(BaseCurrency!="USD") Базовая валюта НЕ доллар США
      {if((CotirCurrency=="USD")||(OilCurrency=="Oil"))//XXXUSD или UxOil (фактически USOUSD) Обратная котировка, Валюта котировки доллар США, стоимость лота $ContractSize*PriceXXX
      {
         /*Расчет стоимости пункта в обратной котировке
         В обратных котировках 1 пункт объемом 100 000 всегда равен 1 доллару США, независимо от текущего курса.
         Для примера возьмем пару EUR/USD. Здесь доллар не является базовой валютой, и все операции производятся с евро. 
         Если курс EUR/USD 1.40000, то 100 000 EUR (объем позиции) = 140 000 USD. 
         Если цена прошла в нужном нам направлении 1 пункт, курс будет 1.40001, 100 000 EUR = 140 001 USD, доход составил 1 доллар. 
         Делить полученный результат на текущий курс не нужно, т.к. в обратной котировке стоимость пункта от него не зависит, кроме того, результат мы получили уже в долларах.
         Формула расчета: Цена пункта = объем позиции * размер пункта
         Таким образом, для пары EUR/USD из нашего примера: 100 000 * 0,00001 = 1 $*/
         {if(SymbolSelect(iSymbol,true))//попытка выбрать символ в окне MarketWatch (Обзор рынка)
         {
            return(ContractSize*sPoint);
         }else{
            return(ContractSize*sPoint);
         }}//if(SymbolSelect(iSymbol,true))
      }else{//XXXZZZ //if((CotirCurrency!="USD") Кросс-курс, Базовая валюта НЕ доллар США, Валюта котировки НЕ доллар США, стоимость лота $ContractSize*PriceXXXUSD
         //----- отладка
         //Print("{",iSymbol,"}");
         //Print("{",BaseCurrency,"}");
         //Print("{",CotirCurrency,"}");
         //Print(SymbolInfoDouble(BaseCurrency+"USD",SYMBOL_ASK));
         //Print(SymbolInfoDouble(BaseCurrency+"USD",SYMBOL_BID));
         //Print(ContractSize*(SymbolInfoDouble(BaseCurrency+"USD",SYMBOL_ASK)+SymbolInfoDouble(BaseCurrency+"USD",SYMBOL_BID))/2);
         
         /*Расчет стоимости пункта в кросс-курсах
         В кросс-курсах не присутствует USD. Для примера возьмем GBP/CHF, курс 1.44000.
         Формула расчета: Цена пункта = объем позиции * размер пункта * текущая котировка базовой валюты по отношению к USD / текущий курс валютной пары (кросс-курс)
         Для GBP/CHF: 100 000 * 0.00001 * 1.58000 (курс GBP/USD) / 1.44000 = 1.1 $*/
         {if(!IsTesting())
         {
            //Работаем в реальном режиме
            {if(StringSubstr(iPairs,StringFind(iPairs,"%",StringFind(iPairs,BaseCurrency,1))+1,1)=="0")//Ишем базовую валюту и за ней после % признак перевернутости
            {//Для базовых валют вида XXXUSD для которых есть обратная котировка (например EURUSD) - нормальная не перевёрнутая
               {if(SymbolSelect(BaseCurrency+"USD",true))//попытка выбрать символ в окне MarketWatch (Обзор рынка)
               {
                  //----- отладка
                  //Print("{",iSymbol,"}");
                  //Print(">>",ContractSize*(SymbolInfoDouble(BaseCurrency+"USD",SYMBOL_ASK)+SymbolInfoDouble(BaseCurrency+"USD",SYMBOL_BID))/2);
                  //return(ContractSize*(SymbolInfoDouble(BaseCurrency+"USD",SYMBOL_ASK)));//не работает в тестере
                  {switch(iMode)
                  {
                        case 0://Mid
                           {
                              return(ContractSize*sPoint
                                          *((SymbolInfoDouble(BaseCurrency+"USD",SYMBOL_ASK)+SymbolInfoDouble(BaseCurrency+"USD",SYMBOL_BID))/2.0)
                                          /((SymbolInfoDouble(iSymbol,SYMBOL_ASK)+SymbolInfoDouble(iSymbol,SYMBOL_BID))/2.0)
                                     );
                           }
                        case 1://Ask
                           {
                              return(ContractSize*sPoint
                                          *((SymbolInfoDouble(BaseCurrency+"USD",SYMBOL_ASK)))
                                          /((SymbolInfoDouble(iSymbol,SYMBOL_ASK)))
                                     );
                           }
                        case 2://Bid
                           {
                              return(ContractSize*sPoint
                                          *((SymbolInfoDouble(BaseCurrency+"USD",SYMBOL_BID)))
                                          /((SymbolInfoDouble(iSymbol,SYMBOL_BID)))
                                     );
                           }
                  }}//switch(iMode)
               }else{
                  return(ContractSize*sPoint);
               }}//if(SymbolSelect(BaseCurrency+"USD",true))
            }else{//Для базовых валют вида USDXXX для которых котировка прямая (например USDCAD) в парах XXXYYY (напрмер CADJPY)- перевернутая, так как нет пары CADUSD есть USDCAD 
               //Формула расчета: Цена пункта = объем позиции * размер пункта * (1 / текущая котировка USD по отношению к базовой валюте) / текущий курс валютной пары (кросс-курс)
               {if(SymbolSelect("USD"+BaseCurrency,true))//попытка выбрать символ в окне MarketWatch (Обзор рынка)
               {
                  //Print(ContractSize*(1/SymbolInfoDouble("USD"+BaseCurrency,SYMBOL_ASK)+1/SymbolInfoDouble("USD"+BaseCurrency,SYMBOL_BID))/2);
                  {switch(iMode)
                  {
                        case 0://Mid
                           {
                              return(ContractSize*sPoint
                                          *(1.0/((SymbolInfoDouble("USD"+BaseCurrency,SYMBOL_ASK)+SymbolInfoDouble("USD"+BaseCurrency,SYMBOL_BID))/2.0))
                                          //*((1.0/SymbolInfoDouble("USD"+BaseCurrency,SYMBOL_ASK)+1.0/SymbolInfoDouble("USD"+BaseCurrency,SYMBOL_BID))/2.0)
                                          /((SymbolInfoDouble(iSymbol,SYMBOL_ASK)+SymbolInfoDouble(iSymbol,SYMBOL_BID))/2.0)
                                    );
                           }
                        case 1://Ask
                           {
                              return(ContractSize*sPoint
                                          *(1.0/SymbolInfoDouble("USD"+BaseCurrency,SYMBOL_ASK))
                                          /(SymbolInfoDouble(iSymbol,SYMBOL_ASK))
                                    );
                           }
                        case 2://Bid
                           {
                              return(ContractSize*sPoint
                                          *(1.0/SymbolInfoDouble("USD"+BaseCurrency,SYMBOL_BID))
                                          /(SymbolInfoDouble(iSymbol,SYMBOL_BID))
                                    );
                           }
                  }}//switch(iMode)
               }else{
                  return(ContractSize*sPoint);
               }}//if(SymbolSelect("USD"+BaseCurrency,true))
            }}//if(StringSubstr(iPairs,StringFind(iPairs,"%",StringFind(iPairs,BaseCurrency,1))+1,1)=="0")   
         }else{
            //Работаем в тестере - невозможно получить котировки других валют
            return(ContractSize*sPoint);
         }}//if(!IsTesting())
      }}//if((CotirCurrency=="USD")||(OilCurrency=="Oil"))
   }}//if(BaseCurrency=="USD")
   return(ContractSize*sPoint);
}//CalcTickValue()

Скриншот результатов:


Тест05




 
Taras Slobodyanik:

ээ... то есть вы предполагаете, но рассчитывать не пробовали?

а я не предполагаю, а беру конкретные значения:    комиссия 10, лот 0.1,  MODE_TICKVALUE...
и считаю)

...и пока всё совпадает 


Для красоты пейзажа, я бы "_Point" выразил через "MarketInfo(OrderSymbol(),11)", чтобы, что то такое было: MarketInfo(OrderSymbol(),MODE_TICKVALUE) * (int)MarketInfo(OrderSymbol(),MODE_POINT);.

Для мультивалютника, более приемлемая комбинация, а на одноинструментный не влияет, если фильтр по символу применён, поскольку комиссия интересует по ордеру. При небольшой пределке, можно применить и к свопу.

 

А я склоняюсь к следующей формуле:

double tickValue = MarketInfo(Symbol(), MODE_TICKVALUE);
double tickSize = MarketInfo(Symbol(), MODE_TICKSIZE);

((OrderCommission() + OrderSwap()) / (tickValue * OrderLots()) * tickSize);


Опровергните меня, если я неправ.

Причина обращения: