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

 
Alexey Viktorov:

Меня смутила вот эта строка

Размер стандартного лота не у всех 100к. Сюда лучше взять SYMBOL_TRADE_CONTRACT_SIZE

Дальше разбираться не осилил, пойду что-нить полезное сделаю.


Согласен с замечанием, но на моих счетах 100к, поэтому не заморачивался.
 
Yury Kirillov:

Согласен с замечанием, но на моих счетах 100к, поэтому не заморачивался.

Да я не против, но...

Yury Kirillov:


Ну и держите, может кому сгодится...

может кто и не сумеет исправить...


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

 
Yury Kirillov:

Увы МТ4

MODE_TICKVALUE - прекрасно всё считает, именно для таких случаев он и создан

comission_pips = sum_comission / order_lots / MarketInfo(Symbol(),MODE_TICKVALUE) * _Point;

где:

  • sum_comission — сумма комиссий, ордеров;
  • order_lots — сумма лотов, ордеров;
  • comission_pips — результат, комиссия в пипсах данного инструмента.
пс. ну и не забываем, что для бай-ордеров эти пипсы прибавляем, а для селл-ордеров отнимаем...
 
Taras Slobodyanik 2017.04.05 22:47     RU
Yury Kirillov:

Увы МТ4

MODE_TICKVALUE - прекрасно всё считает, именно для таких случаев он и создан

comission_pips = sum_comission / order_lots / MarketInfo(Symbol(),MODE_TICKVALUE) * _Point;

где:

  • sum_comission — сумма комиссий, ордеров;
  • order_lots — сумма лотов, ордеров;
  • comission_pips — результат, комиссия в пипсах данного инструмента.
пс. ну и не забываем, что для бай-ордеров эти пипсы прибавляем, а для селл-ордеров отнимаем...

MODE_TICKVALUE считает не настолько прекрасно, как хотелось бы.

1. Для обратных котировок, например EURUSD, считает правильно, ибо тут всё просто: ContractSize*Point

2. Для прямых котировок, например USDRUB, считает по цене BID: ContractSize*Point/SymbolInfoDouble(iSymbol,SYMBOL_BID)

3. Для кросс-курсов у которых для базовой валюты есть обратная котировка иногда считает правильно, например EURJPY, а иногда неправильно вовсе, например EURCHF, а иногда по цене близкой к MID, например EURCAD.

4. Для кросс-курсов у которых для базовой валюты котировка прямая, например CADJPY, считает правильно, хотя непонятно по какой цене Bid или Ask, моя функция почему-то по любой цене выдает одинаковый результат.

То есть в случае 3 непонятно по какой формуле и цене считается встроенный расчет Tick Value. 

Сравнительные результаты расчетов:

Tick Value Test

Скрипт для расчета значений Tick Value:

//+------------------------------------------------------------------+
//|                                  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
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart(){
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.2000. Рассчитаем цену пункта для операции объемом 10 000 (0.1 лот) базовой валюты. 
      Исходя из текущего курса: 10 000 USD = 12 000 CHF.
      Предположим, что цена прошла в нужном нам направлении 1 пункт, и текущий курс составил 1.2001. 10 000 долларов в данном случае уже будет стоить 12 001 франков. Следовательно, мы заработали 1 швейцарский франк. Теперь нужно перевести это значение в американские доллары. Для этого нужно разделить прибыль на текущий курс: 1 / 1.2001 = 0.83 $. Это и есть цена одного пункта по паре USD/CHF.
      Формула расчета: Цена пункта = объем позиции * размер пункта / текущий курс
      Для разобранного выше примера по паре USD/CHF:
      10 000 (объем позиции) * 0,0001 (один пункт) / 1,2001 (текущий курс) = 0,83 $.*/
      {switch(iMode)
      {
            case 0://Mid
               {
                  return(ContractSize*sPoint/((SymbolInfoDouble(iSymbol,SYMBOL_ASK)+SymbolInfoDouble(iSymbol,SYMBOL_BID))/2));
               }
            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 пункт объемом 10 000 всегда равен 1 доллару США, независимо от текущего курса.
         Для примера возьмем пару EUR/USD. Здесь доллар не является базовой валютой, и все операции производятся с евро. 
         Если курс EUR/USD 1.4000, то 10 000 EUR (объем позиции) = 14 000 USD. Если цена прошла в нужном нам направлении 1 пункт, курс будет 1.4001, 10 000 EUR = 14 001 USD, доход составил 1 доллар.
         Делить полученный результат на текущий курс не нужно, т.к. в обратной котировке стоимость пункта от него не зависит, кроме того, результат мы получили уже в долларах.
         Формула расчета: Цена пункта = объем позиции * размер пункта
         Таким образом, для пары EUR/USD из нашего примера: 10 000 * 0,0001 = 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.4400.
         Формула расчета: Цена пункта = объем позиции * размер пункта * текущая котировка базовой валюты по отношению к USD / текущий курс валютной пары (кросс-курс)
         Для GBP/CHF: 10 000 * 0.0001 * 1.5800 (курс GBP/USD) / 1.4400 = 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)
                                          /((SymbolInfoDouble(iSymbol,SYMBOL_ASK)+SymbolInfoDouble(iSymbol,SYMBOL_BID))/2)
                                     );
                           }
                        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 
               {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/SymbolInfoDouble("USD"+BaseCurrency,SYMBOL_ASK)+1/SymbolInfoDouble("USD"+BaseCurrency,SYMBOL_BID))/2)
                                          /((SymbolInfoDouble(iSymbol,SYMBOL_ASK)+SymbolInfoDouble(iSymbol,SYMBOL_BID))/2)
                                    );
                           }
                        case 1://Ask
                           {
                              return(ContractSize*sPoint
                                          *(1/SymbolInfoDouble("USD"+BaseCurrency,SYMBOL_ASK))
                                          /(SymbolInfoDouble(iSymbol,SYMBOL_ASK))
                                    );
                           }
                        case 2://Bid
                           {
                              return(ContractSize*sPoint
                                          *(1/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()
 
Yury Kirillov:

MODE_TICKVALUE считает не настолько прекрасно, как хотелось бы.

1. Для прямых котировок, например EURUSD, считает правильно, ибо тут всё просто.

2. Для обратных котировок, например USDRUB, считает по цене BID.

3. Для кросс-курсов у которых для базовой валюты есть прямая котировка иногда считает правильно, например EURJPY, а иногда неправильно вовсе, например EURCHF, а иногда по цене близкой к ASK, например EURCAD.

4. Для кросс-курсов у которых для базовой валюты котировка обратная, например CADJPY, считает правильно.

Сравнительные результаты расчетов:


Скрипт для расчета значений Tick Value:

Юрий, MODE_TICKVALUE равно как и SYMBOL_TRADE_TICK_VALUE считают стоимость одного пункта (последнего знака котировки) в валюте депозита.

MODE_TICKVALUE

16

Размер минимального изменения цены инструмента в валюте депозита


Размер комиссии считается тоже в валюте депозита. Соответственно пункты умноженные на стоимость 1 пункта дают прибыль\убыток в валюте депозита. И отсюда следует, что деление валюты на ту-же валюту дают количество пунктов. Арифметика не дальше третьего класса.

Или Вы не о том о чём все остальные говорят... В каких пунктах Вы хотите посчитать размер комиссии? В какой валюте комиссия? Разве не в валюте депозита?

 
Alexey Viktorov:

Юрий, MODE_TICKVALUE равно как и SYMBOL_TRADE_TICK_VALUE считают стоимость одного пункта (последнего знака котировки) в валюте депозита.

MODE_TICKVALUE

16

Размер минимального изменения цены инструмента в валюте депозита


Размер комиссии считается тоже в валюте депозита. Соответственно пункты умноженные на стоимость 1 пункта дают прибыль\убыток в валюте депозита. И отсюда следует, что деление валюты на ту-же валюту дают количество пунктов. Арифметика не дальше третьего класса.

Или Вы не о том о чём все остальные говорят... В каких пунктах Вы хотите посчитать размер комиссии? В какой валюте комиссия? Разве не в валюте депозита?

Приветствую, Алексей!

Ответы:

В каких пунктах Вы хотите посчитать размер комиссии? - в пунктах минимального изменения цены.

В какой валюте комиссия? Разве не в валюте депозита? - комиссия в валюте депозита.

Вопросы:

1. В Вашем: "Соответственно пункты умноженные на стоимость 1 пункта дают прибыль\убыток в валюте депозита." Какая "стоимость 1 пункта" имелась в виду по какой цене: Bid или Ask? Что об этом говорят арифметика с геометрией? :-)

2. Если можно, то поясните пожалуйста, как правильно считается Tick Value для кросс-курсов у которых для базовой валюты есть обратная котировка, например EURJPY. Естественно не встроенной функцией, а исходя из цен и котировок. Ну как в арифметике какого-нибудь класса. :-)

 

MODE_TICKVALUE считает не настолько прекрасно, как хотелось бы.

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

 
Taras Slobodyanik:

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

Что бы понять, что неправильно посчитано, нужно знать как считать.

Я предполагаю, что в данном случае:

"3. Для кросс-курсов у которых для базовой валюты есть обратная котировка"

Расчет должен быть произведён по формуле:

"Формула расчета: Цена пункта = объем позиции * размер пункта * текущая котировка базовой валюты по отношению к USD / текущий курс валютной пары (кросс-курс)"

В этой формуле могут быть использованы цены (котировки) Ask, Bid (или Средняя (Mid))

На скриншоте приведенном ниже расчет с использованием этой формулы и этих цен даёт неадекватные и непредсказуемые результаты:


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

например EURJPY

Стандартные функции: 0.905

Расчет по среднему: 0.905

Расчет по Ask: 0.905

Расчет по Bid: 0.905

иногда неправильно вовсе,

например EURCHF

Стандартные функции: 0.99643

Расчет по среднему: 0.99637

Расчет по Ask: 0.99634

Расчет по Bid: 0.99640

а иногда по цене близкой к MID,

например EURCAD

Стандартные функции: 0.74399

Расчет по среднему: 0.74400

Расчет по Ask: 0.74397

Расчет по Bid: 0.74402

Сравнительные результаты расчетов:

Tick Value Test

 
Yury Kirillov:

Приветствую, Алексей!

Ответы:

В каких пунктах Вы хотите посчитать размер комиссии? - в пунктах минимального изменения цены.

В какой валюте комиссия? Разве не в валюте депозита? - комиссия в валюте депозита.

Вопросы:

1. В Вашем: "Соответственно пункты умноженные на стоимость 1 пункта дают прибыль\убыток в валюте депозита." Какая "стоимость 1 пункта" имелась в виду по какой цене: Bid или Ask? Что об этом говорят арифметика с геометрией? :-)

2. Если можно, то поясните пожалуйста, как правильно считается Tick Value для кросс-курсов у которых для базовой валюты есть обратная котировка, например EURJPY. Естественно не встроенной функцией, а исходя из цен и котировок. Ну как в арифметике какого-нибудь класса. :-)

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

Соответственно ответ на

1. Зависит от направления сделки.

2. Я до такого класса не доучился и это ещё одна причина по которой правильно посчитать самостоятельно я не берусь. Не знаю...

 

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

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

comission_pips = sum_comission / order_lots / MarketInfo(Symbol(),MODE_TICKVALUE) * _Point;

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

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