Индикатор опционных уровней

 

В последнее время у меня возникла идея создания индикатора опционных уровней, основанного на системе Ильдара Нургалиева. В общем-то я никого не рекламирую и коммерческого интереса не имею, мои скромные наработки основаны на материалах, находящихся в открытом доступе.

Yotube: https://www.youtube.com/channel/UClZo081odiV1tVTnXPLY13w
Методичка по ТС https://yadi.sk/i/MAF5UJS63PGsqX
Excel файл для расчетов 
https://vk.com/doc2034145_453816131?hash=a5e52256e0251b482c&dl=279f30310d4aa2ee4e
Группа Вконтакте https://vk.com/traderbar_lenta

Методику объяснять в деталях я не стану, все желающие могут ознакомиться на ютуб-канале автора.

В общем методика основывается на следующем.
С сайта http://cmegroup.quikstrike.net ежедневно необходимо брать данные по ценам опционов текущего страйка по выбранным фьючерсам (валюты, нефть, золото и т. д.) Используются данные либо по месячным опционам (больше по нефти и золоту), или по по недельным опционам с экспирацией через 3 недели ("3-ехнедельные опционы"). Данные необходимо брать со вкладки Pricing Sheets.
Данные получаются вчерашние, по формулам в файле эксель по ним пересчитываются сегодняшние показатели.
Рассчитываются точки безубыточности по колл и пут опционам для текущего страйка, а также верхний и нижний уровни стрэддла для этого же страйка. Они принимаются за уровни вероятного дисбаланса. Т.е. рассматриваются как возможные уровни пробоя/отбоя. Уровни стрэддла автор рекомендует использовать скорее для постановки стоп-лоссов. 
Конечно, эти уровни следует использовать вместе с другими - POC недели, месяца, тенденции и/или иными уровнями повышенного объема.

Иными словами, в этой методике ежедневно используются расчетные уровни, не привязанные напрямую к каким-то объемам.
Кроме всего прочего, за несколько недель я обнаружил, что эти уровни Нургалиева (назовем их так условно), часто примерно соответствуют положению лент Боллинджера с периодом 200-300 (+/- 2 СКО) на часовом графике (т. е. период скользящих примерно соответствует тем же 3 неделям, как у Нургалиева).
Поскольку эти уровни рассчитываются по известной формуле (модель Блэка-Шоулза), у меня возникла идея создать индикатор, напоминающий ленты Боллинджера (только верхняя лента представляет собой точку безубыточности для колл опциона, а нижняя - для пут опциона).

Кое-что по этой теме я уже собрал и попробовал сделать.

Bands Probability.zip - моя переделка стандартного индикатора.

Источники информации:

https://en.wikipedia.org/wiki/Black–Scholes_model
Русский вариант, но формулы с неточностями https://ru.wikipedia.org/wiki/Модель_Блэка_—_Шоулза

https://ru.wikipedia.org/wiki/Волатильность

Парочку примечаний по коду.
Формула для определения страйка рассчитана на пары типа EURUSD, GBPUSD, AUDUSD.
У них страйки выглядят типа 1,1250 - 1,1300 - 1,1350.
Потому для определения текущего страйка я использовал формулу в mt4:

round(spot-price*200)/200

Для других пар (перевернутые JPYUSD, CHFUSD, CADUSD и XAU, WTI) формулы немного будут отличаться коэффициентами, если я не ошибаюсь.
Risk free rate - безрисковая процентная ставка. По словам автора второго эксель-файла, она соответствует % ставке по казначейским облигациям соответствующего срока (т. е. 1 месяц), так как опционы/фьючерсы покупаются за доллары. Ее берут здесь:

ExpDate - дата экспирации месячного валютно опциона (одинаковая для все валют, взята с cmegroup.quikstrike.net).
Конечно, мне могут возразить, что у меня не учитываются форвард-пойнты, но это всего лишь модель ориентировочных уровней. Стоит заметить, даже у Нургалиева его уровни не отрабатываются точно пункт в пункт.

В архиве mql4 внешняя библиотека со стат. функциями. Распаковать в соответствующие папки mql4.
Visual Option - файлы с формулами для образца.
Принцип расчета волатильности брал отсюдаВолатильность я считал через среднее квадратичное отклонение с пересчетом (условно) на месяц и дальше в проценты за месяц, затем -пересчитывал на год. Наверно,здесь ошибка. Подскажите, как правильно. 

Может, кто-нибудь подскажет, почему вообще ничего не рисует?

Подскажите, пожалуйста. Буду очень благодарен.

Файлы:
 

Послушал опытных людей. Все переделал.

Посмотрите, пожалуйста, в чем дело. Не понимаю, почему вообще ничего не рисует.

Все в одном файле. Все пояснения и формулы в комментариях. Для работы нужна probability.dll & probability.mqh (mql4.zip в посте выше).

//+------------------------------------------------------------------+

//|                                                        Bands.mq4 |

//|                   Copyright 2005-2014, MetaQuotes Software Corp. |

//|                                              http://www.mql4.com |

//+------------------------------------------------------------------+

#property copyright   "2005-2014, MetaQuotes Software Corp."

#property link        "http://www.mql4.com"

#property description "Bollinger Bands"

#property strict


#include <MovingAverages.mqh>

#include <Probability.mqh>


#property indicator_chart_window

#property indicator_buffers 9

#property indicator_color1 LightSeaGreen

#property indicator_color2 LightSeaGreen

#property indicator_color3 LightSeaGreen

//--- indicator parameters

input int    InpBandsPeriod=20;      // Bands Period

input int    InpBandsShift=0;        // Bands Shift

input double InpBandsDeviations=2.0; // Bands Deviations

//+------------------------------------------------------------------+

//| Custom indicator initialization function                         |

//+----------------------------------------------------------------

extern string ExpDate = "2018.02.10"; //Дата экспирации месячного опциона http://cmegroup.quikstrike.net

extern double DaysInYear=365;  // Количество дней в году, в зависимости от системы расчета, чаще число раб. дней в году

extern double DaysInMonth=30;  // Тоже в месяце

extern double RFreeRate = 1.15;

/*Risk free rate - безрисковая процентная ставка. Cоответствует % ставке по казначейским облигациям соответствующего срока 

(т. е. 1 месяц), так как опционы/фьючерсы покупаются за доллары. Ее берут здесь:

https://www.treasury.gov/resource-c...interest-rates/Pages/TextView.aspx?data=yield

*/

extern string CurrencySymbol = ""; //

//--- buffers

double ExtUpperBuffer[];    //Верхняя линия

double ExtLowerBuffer[];    //Нижняя линия

double ExtStdDevBuffer[];   //Волатильность для соответствующего бара 

double ExtCallBuffer[];     //Коллы для соответствующего бара 

double ExtPutBuffer[];      //Путы для соответствующего бара 

double ExtDeFirstBuffer[];  //D1 для формулы Блэка-Шоулза для соответствующего бара 

double ExtStrikeBuffer[];   //Страйк, ближайший к текущей цене для соответствующего бара 

double ExtMovingBuffer[];   //Средняя линия 

double DTEBuffer[];         //DTE -число дней до экспирации для соответствующего бара 


int OnInit(void)

  {

//--- 1 additional buffer used for counting.

   IndicatorBuffers(9);

   IndicatorDigits(Digits);

//--- middle line

   SetIndexStyle(0,DRAW_LINE);

   SetIndexBuffer(0,ExtMovingBuffer);

   SetIndexShift(0,InpBandsShift);

   SetIndexLabel(0,"Bands SMA");

//--- upper band

   SetIndexStyle(1,DRAW_LINE);

   SetIndexBuffer(1,ExtUpperBuffer);

   SetIndexShift(1,InpBandsShift);

   SetIndexLabel(1,"Bands Upper");

//--- lower band

   SetIndexStyle(2,DRAW_LINE);

   SetIndexBuffer(2,ExtLowerBuffer);

   SetIndexShift(2,InpBandsShift);

   SetIndexLabel(2,"Bands Lower");

//--- work buffer --  Массивы данных для расчетов, не отображаются на графике.

   SetIndexBuffer(3,ExtStdDevBuffer);

   SetIndexBuffer(4,ExtCallBuffer);

   SetIndexBuffer(5,ExtPutBuffer);

   SetIndexBuffer(6,ExtDeFirstBuffer);

   SetIndexBuffer(7,ExtStrikeBuffer);

   SetIndexBuffer(8,DTEBuffer);

//--- check for input parameter

   if(InpBandsPeriod<=0)

     {

      Print("Wrong input parameter Bands Period=",InpBandsPeriod);

      return(INIT_FAILED);

     }

//---

   SetIndexDrawBegin(0,InpBandsPeriod+InpBandsShift);

   SetIndexDrawBegin(1,InpBandsPeriod+InpBandsShift);

   SetIndexDrawBegin(2,InpBandsPeriod+InpBandsShift);

//--- initialization done

   return(INIT_SUCCEEDED);

  }

//+------------------------------------------------------------------+

//| Bollinger Bands                                                  |

//+------------------------------------------------------------------+

int OnCalculate(const int rates_total,

                const int prev_calculated,

                const datetime &time[],

                const double &open[],

                const double &high[],

                const double &low[],

                const double &close[],

                const long &tick_volume[],

                const long &volume[],

                const int &spread[])

  {

   int i,pos;

   double TFCoeff;

//---

   if(rates_total<=InpBandsPeriod || InpBandsPeriod<=0)

      return(0);

//--- counting from 0 to rates_total --- Т.е. бары считаем от самого раннего до самого последнего, самого свежего (так что ли?)

   ArraySetAsSeries(ExtMovingBuffer,false);

   ArraySetAsSeries(ExtUpperBuffer,false);

   ArraySetAsSeries(ExtLowerBuffer,false);

   ArraySetAsSeries(ExtStdDevBuffer,false);

   ArraySetAsSeries(ExtCallBuffer,false);

   ArraySetAsSeries(ExtPutBuffer,false);

   ArraySetAsSeries(ExtDeFirstBuffer,false);

   ArraySetAsSeries(ExtStrikeBuffer,false);

   ArraySetAsSeries(DTEBuffer,false);

   ArraySetAsSeries(close,false);

   ArraySetAsSeries(open,false);

   ArraySetAsSeries(high,false);

   ArraySetAsSeries(low,false);

//--- initial zero

   TFCoeff=PERIOD_D1/Period(); //Коэффициент для пересчета баров с текущего ТФ на дневной, т.к. волатильность нужна дневная

   if(prev_calculated<1)

     {

      for(i=0; i<InpBandsPeriod; i++)

        {

         ExtMovingBuffer[i]=EMPTY_VALUE;

         ExtUpperBuffer[i]=EMPTY_VALUE;

         ExtLowerBuffer[i]=EMPTY_VALUE;

        }

     }

//--- starting calculation

   if(prev_calculated>1)

      pos=prev_calculated-1;

   else

      pos=0;

//--- main cycle

   for(i=pos; i<rates_total && !IsStopped(); i++)

     {

      //--- middle line

      ExtMovingBuffer[i]=SimpleMA(i,InpBandsPeriod,close);     

      //--- calculate and write down StdDev

      //ExtStdDevBuffer[i]=StdDev_Func(i,close,ExtMovingBuffer,TFCoeff*InpBandsPeriod);  - исходный вариант образца * TFCoeff

      //Два варианта волатильности. Одну из двух последующих строк включить/исключить.

      //ExtStdDevBuffer[i]=StdDev_Func(i,open,close,high,low,TFCoeff*InpBandsPeriod)/ExtMovingBuffer[i]*sqrt(DaysInYear*TFCoeff);//Метод Роджерса-Сатчела - Альтернативный вариант волатильности

      ExtStdDevBuffer[i]=iATR(NULL,PERIOD_D1,InpBandsPeriod,round(i/TFCoeff))/ExtMovingBuffer[i]*sqrt(DaysInYear); //Волатильность для каждого бара, выраженная в долях и в годах

      //Взято  с http://bin-brokers.com/simon52.html - Вайн Саймон. Опционы. Полный курс для профессионалов

      ExtStrikeBuffer[i]=Strike(ExtMovingBuffer[i]);

      DTEBuffer[i]=DTE(time[i]);

      ExtDeFirstBuffer[i]= DF(ExtMovingBuffer[i],ExtStrikeBuffer[i], ExtStdDevBuffer[i],DTEBuffer[i]); 

      //Формулы для коллов и путов см. https://en.wikipedia.org/wiki/Black–Scholes_model

      //ndtr - кумулятивная функция распределения стандартного нормального распределения  из Probability.mqh

      ExtCallBuffer[i]=ExtMovingBuffer[i]* ndtr(ExtDeFirstBuffer[i])- ExtStrikeBuffer[i]*MathExp(-RFreeRate/100*DTEBuffer[i])*ndtr(ExtDeFirstBuffer[i]-ExtStdDevBuffer[i]*MathSqrt(DTEBuffer[i]));

      ExtPutBuffer[i]=ExtStrikeBuffer[i]*MathExp(-RFreeRate/100*DTEBuffer[i])*ndtr(ExtStdDevBuffer[i]*MathSqrt(DTEBuffer[i])- ExtDeFirstBuffer[i])-ndtr(-ExtDeFirstBuffer[i])*ExtMovingBuffer[i] ;

        

      //--- upper line

      //ExtUpperBuffer[i]=ExtMovingBuffer[i]+InpBandsDeviations*ExtStdDevBuffer[i]; - исходный вариант образца

      ExtUpperBuffer[i]=ExtMovingBuffer[i]+ExtCallBuffer[i];

      //lower line

      //ExtLowerBuffer[i]=ExtMovingBuffer[i]-InpBandsDeviations*ExtStdDevBuffer[i]; - исходный вариант образца

      ExtUpperBuffer[i]=ExtMovingBuffer[i]-ExtPutBuffer[i];

      //---

     }

//---- OnCalculate done. Return new prev_calculated.

   return(rates_total);

  }

//+------------------------------------------------------------------+

//| Calculate Standard Deviation                                     |

//+------------------------------------------------------------------+

//Метод Роджерса-Сатчела - Альтернативный вариант волатильности

//https://research-journal.org/economical/analiz-razlichnyx-metodov-ocenki-istoricheskoj-volatilnosti-dlya-opcionnoj-torgovli/

double StdDev_Func(int position,const double &open[],const double &close[],const double &high[],const double &low[],int period)

  { 

//--- variables

   double StdDev_rs=0.0; 

//--- check for position

   if(position>=period)

     {

      //--- calcualte StdDev

      for(int i=0; i<period; i++)

         StdDev_rs+=log(high[position-i]*high[position-i]/close[position-i])*log(high[position-i]/open[position-i])+log(low[position-i]/close[position-i])*log(low[position-i]/open[position-i]);

         StdDev_rs=MathSqrt(StdDev_rs/period);

     }     

//--- return calculated value

     return(StdDev_rs);

  }

  

/* Исходный вариант образца

double StdDev_Func(int position,const double &price[],const double &MAprice[],int period)

  {

//--- variables

   double StdDev_dTmp=0.0;

//--- check for position

   if(position>=period)

     {

      //--- calcualte StdDev

      for(int i=0; i<period; i++)

         StdDev_dTmp+=MathPow(price[position-i]-MAprice[position],2);

      StdDev_dTmp=MathSqrt(StdDev_dTmp/period);

     }

//--- return calculated value

   return(StdDev_dTmp);

  }

*/  

  


double Strike (double x)

   {

     string currency;

     

     if (CurrencySymbol=="") currency=Symbol(); //Если нет названия инструмента, берем с текущего графика

        else currency=CurrencySymbol;           //Иначе - любую строку с любым названием

    

    //Определяем ближайший страйк путем округления.

    //USDCAD,USDCHF - перевернутые пары. На СМЕ CADUSD, CHFUSD  и страйки идут соответственно типа (CADUSD) 0,7950-0,8000-0,8050

    //Пример: 1/(round(1/1.334*200)/200)=1.33 Переворот сделан с перспективой для внедрений форвард-пойнта.

    //Золото. Страйки вида 1320-1325-1300. Пример: round(0.2*1322)/0.2=1320

    //Нефть. Страйки вида 63,0-63,5-64. Пример: round(2*63.3)/2=63.5

    //USDJPY. Страйки вида (JPYUSD) 0,00900-0,00905-0,00910. Пример: 1/(round(1/110,7*20000)/20000)=110,497

    //Остальные валютные пары типа eurusd, audusd. У них страйки идут так: 1,2250 - 1,2200 - 1,2150

    //Примеры: round(1,2260*200)/200 = 1,2250; round(1,2190*200)/200=1,2200

                       

    if (currency == "USDCAD" || currency == "usdcad" || currency == "USDCHF" || currency == "usdchf" ) return 1/(round(1/x*200)/200);

        else if (currency == "GOLD" || currency == "XAUUSD" || currency == "gold" || currency == "xauusd") return round(0.2*x)/0.2;

              else if (currency == "OIL" || currency == "USOIL" || currency == "oil" || currency == "usoil" || currency == "BRENT" || currency == "brent" || currency == "WTI" || currency == "wti") return round(2*x)/2;

                   else if (currency == "USDJPY" || currency == "usdjpy") return 1/(round(1/x*20000)/20000);

                        else return round(200*x)/200;                                                                                                                                                                                                             

                       

   }  

double DF (double spot, double strk, double s, double dte) // D1 из формулы Блэка-Шоулза https://en.wikipedia.org/wiki/Black–Scholes_model

    {

      return (log(spot/strk)+(RFreeRate/100+s*s/2)*dte)/(s*sqrt(dte));

    }  

double DTE (datetime days)    //DTE -число дней до экспирации опциона, рассчитывается для каждого бара с учетом даты экспирации опциона  

    {

      double d;   

      if (((StrToTime(ExpDate)- days)/86400)/DaysInYear>0) d=((StrToTime(ExpDate)-days)/86400)/DaysInYear;

      else d=MathPow(10,-10);

      return d;

    }                            

//+------------------------------------------------------------------+



Файлы:
 

Нашел любопытный индикатор по теме.

Осциллятор Блэка-Шоулза. Правда, он не работает у меня. Может, кто-нибудь подскажет, в чем дело?

Файлы:
 

Cделал два новых варианта на основе предыдущих.  Увы, все по-старому...

Файлы:
 
Доброго времени суток. Мой индикатор начал рисовать. Согласно задумке, в нем есть скользящая средняя (оставил пока), lower&upper bands - уровни цен ближайших к деньгам опционов (страйк +/- колл/пут), уровни стрэддла (желтые, страйк+колл+пут, страйк-колл-пут), СМE expected range (ожидаемый диапазон, формула СМЕ).
Волатильность считается как доходность дневная в процентах (т.е. из сегодняшней цены вычитается вчерашняя и все делится на вчерашнюю; затем находится станд. квадратичное отклонение этих доходностей; далее переводится в годовую умножением на корень из числа дней в году).
Возникла проблема, не могу решить. Еще до введения линий СМE expected range индикатор перестал рисовать upper bands независимо от того, какие там присвоены в массиве значения.
Посоветуйте, кто понимает. Видно проблема какая-то с индикаторным буферами, но ошибок в логе компиляции и в "экспертах" в МТ4 нет.
(Волатильность Роджерса пока отключена, позже посмотрю насчет нее.)
//+------------------------------------------------------------------+
//|                                                        Bands.mq4 |
//|                   Copyright 2005-2014, MetaQuotes Software Corp. |
//|                                              http://www.mql4.com |
//+------------------------------------------------------------------+
#property copyright   "2005-2014, MetaQuotes Software Corp."
#property link        "http://www.mql4.com"
#property description "Bollinger Bands"
#property strict

//#include <MovingAverages.mqh>
#define Pi 3.141592653589793238462643
#define a1  0.31938153
#define a2 -0.356563782
#define a3 1.781477937
#define a4 -1.821255978
#define a5 1.330274429
#property indicator_chart_window
#property indicator_buffers 8
#property indicator_color1 LightSeaGreen
#property indicator_color2 LightSeaGreen
#property indicator_color3 LightSeaGreen
#property indicator_color4 clrGold
#property indicator_color5 clrGold
#property indicator_color6 LightSeaGreen
#property indicator_color7 LightSeaGreen
//--- indicator parameters
input int    InpBandsPeriod=20;                      //Bands Period (bars)
input int    InpBandsShift=0;                        //Bands Shift (days)
input double InpBandsDeviations=2.0;                 //Bands Deviations
extern string ExpDate = "2018.02.10";                //Option expiration date 
extern string X="http://cmegroup.quikstrike.net";    //Look at 
extern double DaysInYear=250;                        //Working days in year
extern double DaysInMonth=22;                        //Working days in month
extern string CurrencySymbol = "";                   //
extern double RFreeRate = 1.15;                      //Risk free rate
extern string Y="https://www.treasury.gov/resource-center/data-chart-center/interest-rates/Pages/TextView.aspx?data=yield";    //Looka at 
/*Risk free rate - безрисковая процентная ставка. Cоответствует % ставке по казначейским облигациям соответствующего срока 
(т. е. 1 месяц), так как опционы/фьючерсы покупаются за доллары.*/
double TFCoeff;
int shift;
//--- buffers
double ExtMovingBuffer[];
double ExtUpperBuffer[];
double ExtLowerBuffer[];
double ExtUpStrdlBuffer[];
double ExtLoStrdlBuffer[];
double ExtStdDevBuffer[];
double UpERBuffer[];
double LoERBuffer[];
//double ExtStrikeBuffer[];
//double ExtCallBuffer[];
//double ExtPutBuffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit(void)
  {
   TFCoeff=PERIOD_D1/Period();  //Коэффициент для пересчета баров с текущего ТФ на дневной, т.к. волатильность нужна дневная  
   shift=TFCoeff*InpBandsShift; //Смещение на дни, а не на бары
//--- 1 additional buffer used for counting.
   IndicatorBuffers(6);
   IndicatorDigits(Digits);
//--- middle line
   SetIndexStyle(0,DRAW_LINE);
   SetIndexBuffer(0,ExtMovingBuffer);
   SetIndexShift(0,shift);
   SetIndexLabel(0,"Bands SMA");
//--- upper band
   SetIndexStyle(1,DRAW_LINE);
   SetIndexBuffer(1,ExtUpperBuffer);
   SetIndexShift(1,shift);
   SetIndexLabel(1,"Bands Upper");
//--- lower band
   SetIndexStyle(2,DRAW_LINE);
   SetIndexBuffer(2,ExtLowerBuffer);
   SetIndexShift(2,shift);
   SetIndexLabel(2,"Bands Lower");
//---upper straddle    
   SetIndexStyle(3,DRAW_LINE);
   SetIndexBuffer(3,ExtUpStrdlBuffer);
   SetIndexShift(3,shift);
   SetIndexLabel(3,"Upper Straddle");
//---lower straddle    
   SetIndexStyle(4,DRAW_LINE);
   SetIndexBuffer(4,ExtLoStrdlBuffer);
   SetIndexShift(4,shift);
   SetIndexLabel(4,"Lower Straddle");  
//---upper CME expected range      
   SetIndexStyle(5,DRAW_LINE,STYLE_DOT);
   SetIndexBuffer(5,UpERBuffer);
   SetIndexShift(5,shift);
   SetIndexLabel(5,"Upper CME ER");   
//---lower CME expected range      
   SetIndexStyle(6,DRAW_LINE,STYLE_DOT);
   SetIndexBuffer(6,LoERBuffer);
   SetIndexShift(6,shift);
   SetIndexLabel(6,"Lower CME ER");  
        
//--- work buffer
   SetIndexBuffer(7,ExtStdDevBuffer);
   //SetIndexBuffer(5,ExtStrikeBuffer);
   //SetIndexBuffer(5,ExtCallBuffer);
   //SetIndexBuffer(6,ExtPutBuffer);
//--- check for input parameter
   if(InpBandsPeriod<=0)
     {
      Print("Wrong input parameter Bands Period=",InpBandsPeriod);
      return(INIT_FAILED);
     }
//---
   SetIndexDrawBegin(0,InpBandsPeriod+shift);
   SetIndexDrawBegin(1,InpBandsPeriod+shift);
   SetIndexDrawBegin(2,InpBandsPeriod+shift);
   SetIndexDrawBegin(3,InpBandsPeriod+shift);
   SetIndexDrawBegin(4,InpBandsPeriod+shift);
   SetIndexDrawBegin(5,InpBandsPeriod+shift);
   SetIndexDrawBegin(6,InpBandsPeriod+shift);
//--- initialization done
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Bollinger Bands                                                  |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
   int i,pos,daybar;
   double call,put,strike,prw,StdDev,timebar,vltl;
//---
   if(rates_total<=InpBandsPeriod || InpBandsPeriod<=0)
      return(0);
//--- counting from 0 to rates_total
   ArraySetAsSeries(ExtMovingBuffer,false);
   ArraySetAsSeries(ExtUpperBuffer,false);
   ArraySetAsSeries(ExtLowerBuffer,false);
   ArraySetAsSeries(ExtUpStrdlBuffer,false);
   ArraySetAsSeries(ExtLoStrdlBuffer,false);
   ArraySetAsSeries(ExtStdDevBuffer,false);
   ArraySetAsSeries(UpERBuffer,false);
   ArraySetAsSeries(LoERBuffer,false);
  //ArraySetAsSeries(ExtStrikeBuffer,false);
  //ArraySetAsSeries(ExtCallBuffer,false);
  //ArraySetAsSeries(ExtPutBuffer,false);
   ArraySetAsSeries(close,false);
   ArraySetAsSeries(open,false);
   ArraySetAsSeries(high,false);
   ArraySetAsSeries(low,false);
//--- initial zero
   if(prev_calculated<1)
     {
      for(i=0; i<InpBandsPeriod; i++)
        {
         ExtMovingBuffer[i]=EMPTY_VALUE;
         ExtUpperBuffer[i]=EMPTY_VALUE;
         ExtLowerBuffer[i]=EMPTY_VALUE;
         ExtUpStrdlBuffer[i]=EMPTY_VALUE;
         ExtLoStrdlBuffer[i]=EMPTY_VALUE;
         UpERBuffer[i]=EMPTY_VALUE;
         LoERBuffer[i]=EMPTY_VALUE;
        }
     }
//--- starting calculation
   if(prev_calculated>1)
      pos=prev_calculated-1;
   else
      pos=0;
      //TFCoeff=PERIOD_D1/Period(); //Коэффициент для пересчета баров с текущего ТФ на дневной, т.к. волатильность нужна дневная
//--- main cycle
   for(i=pos; i<rates_total && !IsStopped(); i++)
     {
      //--- middle line
      ExtMovingBuffer[i]=iMA(NULL,0,InpBandsPeriod,0,MODE_SMA,PRICE_WEIGHTED,rates_total-i);
      //--- calculate and write down StdDev
      //ExtStdDevBuffer[i]=StdDev_Func(i,open,close,high,low,round(TFCoeff*InpBandsPeriod));
      daybar=round((rates_total-i)/TFCoeff); //Номер дневного бара в таймсерии
      if (pos>1)
      ExtStdDevBuffer[i]=(iClose(NULL,PERIOD_D1,daybar)- iClose(NULL,PERIOD_D1,daybar+1))/iClose(NULL,PERIOD_D1,daybar+1);
      //https://studfiles.net/preview/4240292/page:2/
      //https://www.fool.com/knowledge-center/how-to-calculate-annualized-volatility.aspx
      else  ExtStdDevBuffer[i]=0;
      prw=(close[i]+high[i]+low[i]+close[i])/4;
      //StdDev=StdDev_Func(i,open,close,high,low,round(InpBandsPeriod));
      StdDev=StdDev_Func(i,ExtStdDevBuffer,InpBandsPeriod);
      strike=Strike(prw);
      timebar=DTE(time[i]); //DTE для каждого бара
      vltl=StdDev*sqrt(DaysInYear); //Перевод волатильности из дневной в годовую
      //На основе   http://bin-brokers.com/simon52.html - Вайн Саймон. Опционы. Полный курс для профессионалов
      //https://en.wikipedia.org/wiki/Volatility_(finance)
      call=BlackScholes(prw,strike,timebar,vltl,1); //call 1
      put=BlackScholes(prw,strike,timebar,vltl,0);  //put 0
      //ExtStrikeBuffer[i]=Strike(ExtMovingBuffer[i]);
      //--- upper line
      ExtUpperBuffer[i]=strike+call;
      //--- lower line
      ExtLowerBuffer[i]=strike-put;
      //--- Straddles
      ExtUpStrdlBuffer[i]=strike+call+put;
      ExtLoStrdlBuffer[i]=strike-call-put;
      UpERBuffer[i]=strike+ strike* vltl*vltl/2* timebar/365 - ((-1)*vltl*timebar/365);
      LoERBuffer[i]=strike+ strike* vltl*vltl/2* timebar/365 - (vltl*timebar/365);
      //---
      }
       return(rates_total);
 }      
      
//+------------------------------------------------------------------+
/*double StdDev_Func(int position,const double &hopen[],const double &hclose[],const double &hhigh[],const double &hlow[],int period)
  {
//--- variables
   double StdDev_rs=MathPow(10,-10);
//--- check for position
   if(position>=period)
     {
      //--- calcualte StdDev
      for(int i=0; i<period; i++)
           StdDev_rs+=log(hhigh[position-i]/hclose[position-i])*log(hhigh[position-i]/hopen[position-i])+log(hlow[position-i]/hclose[position-i])*log(hlow[position-i]/hopen[position-i]);
         StdDev_rs=MathSqrt(StdDev_rs/period);
         //StdDev_dTmp+=MathPow(price[position-i]-MAprice[position],2);
         //StdDev_dTmp=MathSqrt(StdDev_dTmp/period);
     }
//--- return calculated value
   return(StdDev_rs);
  }
*/ 

double StdDev_Func(int position,const double &dev[],int period)
  {
//--- variables
   double StdDev_dTmp, mean;
   StdDev_dTmp=MathPow(10,-10);
   mean=MathPow(10,-10);
//--- check for position
   if(position>=period)
     {
      //--- calcualte StdDev
      for(int i=0; i<period; i++)
          mean+=dev[i];
      mean=mean/period;
      for(int x=0; x<period; x++)   
          StdDev_dTmp+=MathPow(dev[position-x]-mean,2);
      StdDev_dTmp=MathSqrt(StdDev_dTmp/period);
     }
//--- return calculated value
   return(StdDev_dTmp);
  }
//+------------------------------------------------------------------+
double Strike (double x)
   {
     string currency;
     
     if (CurrencySymbol=="") currency=Symbol(); //Если нет названия инструмента, берем с текущего графика
        else currency=CurrencySymbol;           //Иначе - любую строку с любым названием
    
    //Определяем ближайший страйк путем округления.
    //USDCAD,USDCHF - перевернутые пары. На СМЕ CADUSD, CHFUSD  и страйки идут соответственно типа (CADUSD) 0,7950-0,8000-0,8050
    //Пример: 1/(round(1/1.334*200)/200)=1.33 Переворот сделан с перспективой для внедрений форвард-пойнта.
    //Золото. Страйки вида 1320-1325-1300. Пример: round(0.2*1322)/0.2=1320
    //Нефть. Страйки вида 63,0-63,5-64. Пример: round(2*63.3)/2=63.5
    //USDJPY. Страйки вида (JPYUSD) 0,00900-0,00905-0,00910. Пример: 1/(round(1/110,7*20000)/20000)=110,497
    //Остальные валютные пары типа eurusd, audusd. У них страйки идут так: 1,2250 - 1,2200 - 1,2150
    //Примеры: round(1,2260*200)/200 = 1,2250; round(1,2190*200)/200=1,2200
                       
    if (currency == "USDCAD" || currency == "usdcad" || currency == "USDCHF" || currency == "usdchf" ) return 1/(round(1/x*200)/200);
        else if (currency == "GOLD" || currency == "XAUUSD" || currency == "gold" || currency == "xauusd") return round(0.2*x)/0.2;
              else if (currency == "OIL" || currency == "USOIL" || currency == "oil" || currency == "usoil" || currency == "BRENT" || currency == "brent" || currency == "WTI" || currency == "wti") return round(2*x)/2;
                   else if (currency == "USDJPY" || currency == "usdjpy") return 1/(round(1/x*20000)/20000);
                        else return round(200*x)/200;                                                                                                                                                                                                             
                       
   }

double DTE (datetime days)    //DTE -число дней до экспирации опциона, рассчитывается для каждого бара с учетом даты экспирации опциона  
    {
      double d;   
      if (((StrToTime(ExpDate)- days)/86400)/DaysInYear>0) d=((StrToTime(ExpDate)-days)/86400)/DaysInYear;
      else d=MathPow(10,-10);
      return d;
    }   
                                

double BlackScholes(double spot, double strike, double dte,  double vol, int type)
//Формулы для коллов и путов см. https://en.wikipedia.org/wiki/Black–Scholes_model
{
        double d1, d2;
        double res;
        
        d1=(MathLog(spot/strike)+(RFreeRate/100+vol*vol/2)*dte)/(vol*MathSqrt(dte));
        d2=d1-vol*MathSqrt(dte);

        if(type==1) //call
        {
                res=  spot *CumulDistrib(d1)-strike * MathExp(-RFreeRate/100*dte)*CumulDistrib(d2);
                return(res);
}
        else
                if(type==0) //put
                {
                        res= strike * MathExp(-RFreeRate/100 * dte) * CumulDistrib(-d2) - spot * CumulDistrib(-d1);
                        return(res);                    
                }
                else 
                        {
                        res = 0;
                        return(0);
                        }
}

// The cumulative normal distribution function 
double CumulDistrib( double a_X )
{

        double L, K, w ;

        L = MathAbs(a_X);
        K = 1.0 / (1.0 + 0.2316419 * L);
        w = 1.0 - 1.0 / (MathSqrt(2 * Pi)) * (MathExp(-L *L / 2)) * ((a1 * K) + (a2 * K *K) + (a3 * MathPow(K,3)) +( a4 * MathPow(K,4) )+ (a5 * MathPow(K,5)));

if (a_X < 0 )
       {
       w= 1.0 - w;
       }
  return(w);
}

  

Файлы:
indicator.ZIP  26 kb
 
ищу программиста есть уровни с 100% отработкой нужно написать индикатор в ручную надоело каждый день писать***
 
Vadim1985:
ищу программиста есть уровни с 100% отработкой нужно написать индикатор в ручную надоело каждый день писать***
Вам сюда
 
Немного обновил. Два варианта - самостоятельный и с функцией из  probability.dll (выкладывал раньше). Уменьшил число итераций при подсчете дневной волатильности.
Может ли кто-нибудь посмотреть, почему не рисуются линии bands lower, CME ER lower & upper? 
Явных ошибок вроде бы нет (согласно компилятору и вкладке "эксперты").
Файлы:
Indicators.zip  11 kb