import os
import pandas as pd
import numpy as np
import pandas.io.data as web
import datetime
import math
import sys

from pandas.io import sql
import MySQLdb

from pandas_datareader import data, wb

from app.model.NewtonRaphson import NewtonRaphson
from app.processor.DBParameter import *

class ImpliedVolatilityProcessor:


    @staticmethod
    def calculate(ticker, quoteDate):
        #ticker = 'SPY'
        today = datetime.date.today()
        
        try:
            optionReader = data.Options(ticker, 'yahoo')
            option = optionReader.get_all_data()
        except Exception as e:
            print 'Error occur while reading options data from Yahoo: ' + str(e)
            raise

        optionResult = None
        nr = NewtonRaphson()

        for expiryDate in optionReader.expiry_dates:
            diff = expiryDate - today
            expiryDays = diff.days

            callOptions = optionReader.get_call_data(expiry=expiryDate)
            callOptions = callOptions.drop('JSON', 1)
            ImpliedVolatilityProcessor.calculateImpliedVolatility(callOptions, expiryDays, nr)
        
            putOptions = optionReader.get_put_data(expiry=expiryDate)
            putOptions = putOptions.drop('JSON', 1)
            ImpliedVolatilityProcessor.calculateImpliedVolatility(putOptions, expiryDays, nr)
            
            
            optionResult = pd.concat([optionResult, callOptions, putOptions])
        
        optionResult['Quote_Param'] = quoteDate
        #print optionResult
        
        # Save result
        appPath = os.path.dirname(__file__) + '/../../..'
        fileName = appPath + '/configure/iv/' + today.strftime('%Y%m%d-') + ticker + '.data'
        
        # save to csv file
        #optionResult.to_csv(fileName, sep=',', encoding='utf-8')
        
        # save to mysql
        ImpliedVolatilityProcessor.saveToMySQL(optionResult)
        
        return len(optionResult.index)
            
            
    @staticmethod
    def calculateImpliedVolatility(options, expiryDays, nr):
        dividendYield = 0
        riskfreeRate = 0.005
        expiryYears = expiryDays / 365.
        
        volBid = []
        volAsk = []
        volMid = []
        for row_index, row in options.iterrows():
            Strike, Expiry, Type, Symbol = row_index
            
            volatilityBid = nr.calculateVolatility(row['Bid'], Type, 
                                            row['Underlying_Price'], Strike, expiryYears, dividendYield, riskfreeRate)
            volBid.append(volatilityBid)
            
            volatilityAsk = nr.calculateVolatility(row.Ask, Type, 
                                            row.Underlying_Price, Strike, expiryYears, dividendYield, riskfreeRate)
            volAsk.append(volatilityAsk)
            
            volatilityMiddle = nr.calculateVolatility((row.Bid + row.Ask)/2., Type, 
                                            row.Underlying_Price, Strike, expiryYears, dividendYield, riskfreeRate)
            volMid.append(volatilityMiddle)
        
        options['Expiry_Days'] = expiryDays
        options['Bid_IV'] = volBid
        options['Ask_IV'] = volAsk
        options['Middle_IV'] = volMid


    @staticmethod
    def saveToMySQL(optionResult):
        db = MySQLdb.connect(DBParameter.HOST_NAME, DBParameter.USER_NAME, DBParameter.PASSWORD, DBParameter.DB_NAME)
        #cursor = db.cursor()

        #sql.write_frame(optionResult, con=db, name='IV', if_exists='replace', flavor='mysql')
        #optionResult.to_sql(name='IV', con=db, if_exists = 'replace', index=True, flavor='mysql')
        optionResult.to_sql(name='IV', con=db, if_exists = 'append', index=True, flavor='mysql')

        db.close()
