Here it is code with comments.
//+------------------------------------------------------------------+ //| 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"; //Date of expiration of option http://cmegroup.quikstrike.net extern double DaysInYear=365; //Quantity of working days in the year extern double DaysInMonth=30; // ... in the month extern double RFreeRate = 1.15; /*Risk free rate https://www.treasury.gov/resource-c...interest-rates/Pages/TextView.aspx?data=yield */ extern string CurrencySymbol = ""; // //--- buffers double ExtUpperBuffer[]; //Upper band double ExtLowerBuffer[]; //Lower band double ExtStdDevBuffer[]; //Volatility for every bar double ExtCallBuffer[]; //Calls counted for every bar double ExtPutBuffer[]; //Puts counted for every bar double ExtDeFirstBuffer[]; //D1 for Black-Showels formula for every bar double ExtStrikeBuffer[]; //The nearest strike to current price double ExtMovingBuffer[]; //Middle line double DTEBuffer[]; //DTE - days to expiration for every bar 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 -- (not drawn on the chart) 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 --- Bars are counted from earler to newer ones 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(); //Difference of the current TF and D1, needed for daily volatility calculations 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); - initial formula from the stanadard indicator with my multiplier * TFCoeff //Two formulae for volatitilty. Try either //ExtStdDevBuffer[i]=StdDev_Func(i,open,close,high,low,TFCoeff*InpBandsPeriod)/ExtMovingBuffer[i]*sqrt(DaysInYear*TFCoeff);//Rogers-Satchell Volatility //https://www.rdocumentation.org/packages/TTR/versions/0.23-2/topics/volatility //https://www.quantshare.com/item-192-rogers-satchell-volatility-estimator ExtStdDevBuffer[i]=iATR(NULL,PERIOD_D1,InpBandsPeriod,round(i/TFCoeff))/ExtMovingBuffer[i]*sqrt(DaysInYear); //Daily volatility expressed in years //Taken from 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]); //Call and put formulae https://en.wikipedia.org/wiki/Black–Scholes_model //ndtr - cumulative standard normal distribution function from 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]; - initial formula from the stanadard indicator ExtUpperBuffer[i]=ExtMovingBuffer[i]+ExtCallBuffer[i]; //lower line //ExtLowerBuffer[i]=ExtMovingBuffer[i]-InpBandsDeviations*ExtStdDevBuffer[i]; - initial formula from the stanadard indicator ExtUpperBuffer[i]=ExtMovingBuffer[i]-ExtPutBuffer[i]; //--- } //---- OnCalculate done. Return new prev_calculated. return(rates_total); } //+------------------------------------------------------------------+ //| Calculate Standard Deviation | //+------------------------------------------------------------------+ //Rogers-Satchell Volatility //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); } /* Initial function from the stanadard indicator 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(); // If currency symbol isn't inserted the indicator takes it from the current window chart else currency=CurrencySymbol; //else - inserted string //Determine the nearest strike with round function. //USDCAD,USDCHF - upset paires. At СМЕ they correspond to CADUSD, CHFUSD. Their strikes look like (CADUSD) 0,7950-0,8000-0,8050 //E.g.: 1/(round(1/1.334*200)/200)=1.33 //Golden strikes look like 1320-1325-1300. E.g: round(0.2*1322)/0.2=1320 //Oil strikes are 63,0-63,5-64. E.g.: round(2*63.3)/2=63.5 //USDJPY. Strikes are (JPYUSD) 0,00900-0,00905-0,00910. E.g.: 1/(round(1/110,7*20000)/20000)=110,497 //Other foreign exchange looks like eurusd, audusd. Their strikes are: 1,2250 - 1,2200 - 1,2150 //E.g: 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 from Black formula 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 -days to expiration for every bar. It uses option expiration date. { double d; if (((StrToTime(ExpDate)- days)/86400)/DaysInYear>0) d=((StrToTime(ExpDate)-days)/86400)/DaysInYear; else d=MathPow(10,-10); return d; } //+------------------------------------------------------------------+
Files:
indicator.ZIP
21 kb
probability.zip
50 kb
When you post code please use the SRC button! Please edit your post.
General rules and best pratices of the Forum. - General - MQL5 programming forum
General rules and best pratices of the Forum. - General - MQL5 programming forum
You are missing trading opportunities:
- Free trading apps
- Over 8,000 signals for copying
- Economic news for exploring financial markets
Registration
Log in
You agree to website policy and terms of use
If you do not have an account, please register
I'd like to make option levels indicator for MT4. My Russian version of topic is at https://www.mql5.com/ru/forum/224805
Here it is my idea. According to one theory (Ildar Nurgaliev, Russian https://www.youtube.com/channel/UClZo081odiV1tVTnXPLY13w?app=desktop) price moves from volume to volume. The nearest sources of volume correspond to option levels which are at-the-money. These levels are located at the strike nearest to current price (open session or close of preivous session for example). The author of the trading system suggests to use every day the nearest to current price strike and breakeven points of its call and put options. He builds such call and put levels using pricing sheets from CME monthly or 3-week to expiration option (foreign exchange, oil, gold) taken from QuikStrike http://cmegroup.quikstrike.net .
These levels do not correspond to any volume. The levels are calculated with Black-Showels formula.
(https://en.wikipedia.org/wiki/Black–Scholes_model)
So I've decided to make an indicator looking like Bollinger Bands but with breakeven points of call and put options.
I've made a version but it doesn't draw anything even simple moving average. It includes probability.dll (in archive). Please anyone help to find errors.