Стоимость 1 пункта и другие параметры ордера. - страница 2

 
User_mt5:

Но судя по всему, правильные ответы соответственно 1.1246 и 1.0 (я хочу вычислить значения в валюте счёта, счёт открыт в $)


По идее, все верно. Только не хватает информации о величине пункта. Что выдает SymbolInfo(Symbol(), SYMBOL_POINT)?
 
Ihor Herasko:

По идее, все верно. Только не хватает информации о величине пункта. Что выдает SymbolInfo(Symbol(), SYMBOL_POINT)?

Возможно, всё и верно, но пока я не понимаю как это закодировать.

Вот немного дополнил про SYMBOL_POINT :

void OnStart()
   {  
   Alert(" ===============================================================");
// SYMBOL_TRADE_TICK_VALUE_PROFIT Рассчитанная стоимость тика для прибыльной позиции
// SYMBOL_TRADE_TICK_SIZE  Минимальное изменение цены
// Стоимость 1 пункта:
   double pips = SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_VALUE_PROFIT);
   double stts = SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_SIZE);
   double sypo = SymbolInfoDouble(Symbol(), SYMBOL_POINT);
   Alert("pips = ", pips, "     stts = ", stts, "     sypo = ", sypo, "     Стоимость 1 пункта (1 лот)  =  ", pips / stts);
   }

Результаты такие:

Dax30:       pips = 0.1     stts = 0.1     sypo = 0.1     Стоимость 1 пункта (1 лот)  =  1.0

EUR/USD:  pips = 1.0     stts = 1e-05     sypo = 1e-05     Стоимость 1 пункта (1 лот)  =  99999.99999999999

И что с этим можно сделать полезного?

 
User_mt5:

И что с этим можно сделать полезного?

Во-первых, для определения стоимости тика лучше использовать SYMBOL_TRADE_TICK_VALUE, а не SYMBOL_TRADE_TICK_VALUE_PROFIT. Как Вы показали в примере, этот параметр не всегда правильно заполнен.

Во-вторых, если посмотреть спецификацию контракта по DAX, то увидим следующее:

Видно, что валюта залога и валюта прибыли указана в EUR. Таким, образом, Вы получаете правильную информацию, но только не для валюты своего счета. Далее нужно брать текущую котировку EURUSD и по ней уже пересчитывать стоимость пункта. 

 

Итого. Получаем такой алгоритм расчета стоимости пункта:

void OnStart()
{  
   double tickValue = SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_VALUE);
   double stts = SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_SIZE);
   string profitCurrency = SymbolInfoString(Symbol(), SYMBOL_CURRENCY_PROFIT);
   
   string accountCurrency = AccountInfoString(ACCOUNT_CURRENCY);
   if (profitCurrency != accountCurrency)
   {
      string sDirect = profitCurrency + accountCurrency;
      if (IsSymbolExists(sDirect))      
         Alert("Стоимость 1 пункта: ", tickValue / stts * SymbolInfoDouble(sDirect, SYMBOL_BID));
      else
      {
         string sReverse = accountCurrency + profitCurrency;
         if (IsSymbolExists(sReverse))      
            Alert("Стоимость 1 пункта: ", tickValue / stts / SymbolInfoDouble(sReverse, SYMBOL_BID));
         else
            Alert("Невозможно рассчитать стоимость пункта.");
      }
        
   }
   else
      Alert("Стоимость 1 пункта:  ", tickValue / stts);   
}
bool IsSymbolExists(string sSymbol)
{
   ResetLastError();
   SymbolInfoDouble(sSymbol, SYMBOL_BID);                      
   int error = GetLastError();
   return !(error == 5040 || (error >= 4301 && error <= 4303));
}

Алгоритм набросан на скорую руку. Здесь нет проверок деления на 0 и, возможно, еще каких-то проверок. Но в целом работает.

 
Ihor Herasko:

Итого. Получаем такой алгоритм расчета стоимости пункта:

Алгоритм набросан на скорую руку. Здесь нет проверок деления на 0 и, возможно, еще каких-то проверок. Но в целом работает.

Спасибо за Ваше внимание и простите мою навязчивость..

Скрипт прекрасно работает на Даксе. Вот если бы он ещё на евре работал, я был бы просто счастлив!))

 
Видимо, не судьба мне узнать как вычисляется стоимость 1 пункта...
 
User_mt5:
Видимо, не судьба мне узнать как вычисляется стоимость 1 пункта...

Судьба ))) Просто надо было разобраться, как это для МТ5 делается. 

void OnStart()
{  
   double fContractSize = SymbolInfoDouble(Symbol(), SYMBOL_TRADE_CONTRACT_SIZE);
   double fPoint = SymbolInfoDouble(Symbol(), SYMBOL_POINT);
   string sProfitCurrency = SymbolInfoString(Symbol(), SYMBOL_CURRENCY_PROFIT);
   string sAccountCurrency = AccountInfoString(ACCOUNT_CURRENCY);

   if (sProfitCurrency != sAccountCurrency)
   {
      string sReverse = sAccountCurrency + sProfitCurrency;
      if (IsSymbolExists(sReverse))      
         Alert("Стоимость 1 пункта: ", fPoint * fContractSize / SymbolInfoDouble(sReverse, SYMBOL_BID));
      else
      {
         string sDirect = sProfitCurrency + sAccountCurrency;
         if (IsSymbolExists(sDirect))      
            Alert("Стоимость 1 пункта: ", fPoint * fContractSize * SymbolInfoDouble(sDirect, SYMBOL_BID));
         else
            Alert("Невозможно рассчитать стоимость пункта.");
      }
        
   }
   else
      Alert("Стоимость 1 пункта:  ", fPoint * fContractSize);   
}
bool IsSymbolExists(string sSymbol)
{
   ResetLastError();
   SymbolInfoDouble(sSymbol, SYMBOL_BID);                      
   int error = GetLastError();
   return !(error == 5040 || (error >= 4301 && error <= 4303));
}

Справедливо для таких способов расчета:

  1. SYMBOL_CALC_MODE_FOREX
  2. SYMBOL_CALC_MODE_CFD
  3. SYMBOL_CALC_MODE_CFDINDEX
  4. SYMBOL_CALC_MODE_CFDLEVERAGE
  5. SYMBOL_CALC_MODE_EXCH_STOCKS

 
Ihor Herasko:

Судьба ))) Просто надо было разобраться, как это для МТ5 делается.

Так-так-так..

Спасибо. Есть надежда. Буду разбираться.

 
User_mt5:

Буду разбираться.


Я уже на блюдечке все преподнес... В чем разбираться?

 
Ihor Herasko:

Я уже на блюдечке все преподнес... В чем разбираться?

Вы, наверное, опытный программёр, и то не с первого раза. А мне нужно было время, чтобы понять. Но я разобрался. Всё стало понятно.

Спасибо огромное!

Сначала насторожило, что есть ситуация, когда невозможно рассчитать. Но потом дошло, что это только для примера. И даже если индекс в тугриках, а депозит в неандертальцах, и такого кросс-курса нету, ..
то нужно найти их кросс через пары тугрик/юзд и неандер/юзд (или наоборотные; с юздом вроде всё есть) и подставить этот курс в расчёт.

Остаётся один последний риторический вопрос: почему всю эту хреномуть разработчики не затолкали в стандартную функцию? Во что-то типа:

SymbolInfoDouble(Symbol(), SYMBOL_СТОИМОСТЬ_ОДНОГО_POINТА_В_ВАЛЮТЕ_ДЕПОЗИТА)

Но это уже не к Вам.

А Вам ещё раз спасибо.