//+-----------------------------------------------------------------+
//|                         				  BlackScholes_oscillator     |
//|    wrote by jaguar1637@yahoo.com                                    |
//|                            http://beathespread.com                         |
//+-----------------------------------------------------------------+
#property copyright "jaguar1637@yahoo.com"
#property link      "http://beathespread.com"
#property strict

#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_separate_window
#property indicator_buffers 1
#property indicator_color1   Navy
#property indicator_width1  2

//---- buffers
double Data[];

//+------------------------------------------------------------------+
enum ENUM_CALL_TYPE { CUMULATIVE, PRODUCT };
extern ENUM_CALL_TYPE  ENUMCallPutFlag     = PRODUCT;
extern bool            debug               = true;
string      CallPutFlag  ;

double Sclose;
extern double 		X90 = 90;
extern double 		T20 = 20;
extern double 		r05 = 0.05;
extern double 		v02 = 0.02;
//+------------------------------------------------------------------+
//| indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
 {
   // EventSetTimer(1);
   //---- indicators
   IndicatorShortName("BlackScholes_oscillator");
   IndicatorBuffers(1);
   SetIndexBuffer(0,Data);
   //------------------------------
   SetIndexLabel(0,"BlackScholes");
   //----
   return(INIT_SUCCEEDED);
 }
//+------------------------------------------------------------------+
//| de-initialization function                                       |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
 {
   //----
   //   EventKillTimer();
   if(debug==true)
      Comment("");
   //----
 }
//+------------------------------------------------------------------+
//| timer function                                                   |
//+------------------------------------------------------------------+
void OnTimer()  //timer should be every minute to coincide with the creation of new bars
 {
   //----
   //---- 
 }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
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 limit;
   if( prev_calculated < 1 ) // first time
    {
       limit=(rates_total-prev_calculated)-1;
    }
   else
    {
       limit=rates_total-prev_calculated;
    }
   //----
	if (ENUMCallPutFlag == PRODUCT)
		CallPutFlag = "p";
	else
		CallPutFlag = "c";
		
	// After I will insert EMA the HP array
	Sclose=Close[0];
	for (int i = limit; i>0; i--)
    {
      Sclose = Close[i];
	   Data[i] = BlackScholes(Sclose,X90,T20,r05,v02);
	 }
	//for (j = 0; j > -10; j--)
	//{
	//S=Close[j];
	//Data[j] = BlackScholes(S,X90,T20,r05,v02);
	//}
   return(rates_total);
 }
 // The Black and Scholes (1973) Stock option formula
double BlackScholes( double sClose, double x90, double t20, double r0_5,double v0_2)
 {
	double d1, d2;
	double res;
	
	d1=(MathLog(sClose/x90)+(r0_5+v0_2*v0_2/2)*t20)/(v0_2*MathSqrt(t20));
	d2=d1-v0_2*MathSqrt(t20);
   
   switch (ENUMCallPutFlag)
    {
      case CUMULATIVE:
         res = sClose * CumulDistrib(d1)-x90 * MathExp(-r0_5 * t20) * CumulDistrib(d2);
         break;
      case PRODUCT:
         res = x90 * MathExp(-r0_5 * t20) * CumulDistrib(-d2) - sClose * CumulDistrib(-d1);
         break;
      default:
         res = 0;
         break;
    }
   // --- put up a debug statement showing res value 
   /*
   static bool posted = false;
   static int callCount=0;
   if( posted==false && debug==true )
    {
      callCount++;
      if(res<0)
      {
         Comment("Res Less Than 0, ", DoubleToStr(res,Digits),", Call: ",IntegerToString(callCount),", D1: ",DoubleToStr(d1,Digits),", D2: ",DoubleToStr(d2,Digits));
         posted = true;
      } else if(res>0)
      {
         Comment("Res Greater Than 0, ", DoubleToStr(res,Digits),", Call: ",IntegerToString(callCount),", D1: ",DoubleToStr(d1,Digits),", D2: ",DoubleToStr(d2,Digits),
                  " Cumul d1: ",DoubleToStr(CumulDistrib(d1),Digits),", Cumul d2: ",DoubleToStr(CumulDistrib(d2),Digits) );
         posted = true;
      } else
      {
         Comment( "Res is 0: ", DoubleToStr(res,Digits),", Call: ",IntegerToString(callCount),", D1: ",DoubleToStr(d1,Digits),", D2: ",DoubleToStr(d2,Digits),
                  " Cumul d1: ",DoubleToStr(CumulDistrib(d1),Digits),", Cumul d2: ",DoubleToStr(CumulDistrib(d2),Digits) );
         // posted = true;
      }
    }
   //
    */
   return(res);
 }
// The cumulative normal distribution function
double CumulDistrib( double dstrb )
 {
	double L, K, w ;
   
	L = MathAbs(dstrb);
	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)));
   // --- put up a debug statement showing Calculations value /*    
   static bool posted = false;
   static int callCount=0;
   if( posted==false && debug==true ) //  && w!=1.0 )
    {
      callCount++;
         Comment("L: ", DoubleToStr(L,Digits),", Call: ",IntegerToString(callCount),", K: ",DoubleToStr(K,Digits),", W: ",DoubleToStr(w,Digits));
         // posted = true;
     }
   // END Debug---- /* 
   if (dstrb < 0 )
    {
       w= 1.0 - w;
    }
   return(w);
 }