# -*- coding: utf-8 -*-
from __future__ import division

import numpy as np
import statsmodels.tsa.stattools as ts
from das.data_handler import *
from config.services import *

from common.stock_common import *
from config.const import *


class AlphaModel():
	def __init__(self):
		self.dbhandler = services.get('dbhandler')
		self.dbreader = services.get('dbreader')
		self.predictor = services.get('predictor')
		self.config = services.get('configurator')

	def determinePosition(self,code,df,column,row_index,verbose=False):
		pass



class MeanReversionModel(AlphaModel):
	def calcADF(self,df):
		adf_result = ts.adfuller(df)
		ciritical_values = adf_result[4]
		#print ciritical_values

		return adf_result[0], ciritical_values['1%'],ciritical_values['5%'], ciritical_values['10%']


	def calcHurstExponent(self,df,lags_count=100):
		
		# range(2, 100) 은 2부터 100미만의 숫자를 포함하는 range 객체를 만들어 준다.
	    lags = range(2, lags_count)
	    
	    # np를 통해 자연로그 log(exp x)로 변환
	    ts = np.log(df)

	    tau = [np.sqrt(np.std(np.subtract(ts[lag:], ts[:-lag]))) for lag in lags]
	    poly = np.polyfit(np.log(lags), np.log(tau), 1)

	    result = poly[0]*2.0

	    return result

	def calcHalfLife(self,df):
	    price = pd.Series(df)  
	    lagged_price = price.shift(1).fillna(method="bfill")  
	    delta = price - lagged_price  
	    beta = np.polyfit(lagged_price, delta, 1)[0] 
	    half_life = (-1*np.log(2)/beta) 

	    return half_life


	def determinePosition(self,df,column,row_index,verbose=False):
		current_price = df.loc[row_index,column]

		df_moving_average = pd.rolling_mean(df.loc[0:row_index,column],window=self.window_size)
		df_moving_average_std = pd.rolling_std(df.loc[0:row_index,column],window=self.window_size)

		#print df.loc[0:row_index,column]
		#print moving_average
		#print df_moving_average_std
		moving_average = df_moving_average[row_index]
		moving_average_std = df_moving_average_std[row_index]

		price_arbitrage = current_price - moving_average

		if verbose:
			print "diff=%s, price=%s, moving_average=%s, moving_average_std=%s" % (price_arbitrage,current_price,moving_average,moving_average_std)

		if abs(price_arbitrage) > moving_average_std*self.threshold:
			
			if np.sign(price_arbitrage)>0:
				return SHORT
			else:
				return LONG

		return HOLD


class MachineLearningModel(AlphaModel):
	def calcScore(self,split_ratio=0.75,time_lags=10):
		return self.predictor.trainAll(split_ratio=split_ratio,time_lags=time_lags )


	def determinePosition(self,code,df,column,row_index,verbose=False):
		if (row_index-1) < 0:
			return HOLD

		current_price = df.loc[row_index-1,column]

		prediction_result = 0
		for a_predictor in ['logistic','rf','svm']:
			
			predictor = self.predictor.get(code,a_predictor)
			pred,pred_prob = predictor.predict([current_price])

			#print "predictor=%s, price=%s, pred=%s, pred_proba=%s" % (a_predictor,current_price,pred[0],pred_prob[0])

			prediction_result += pred[0]
			#print prediction_result[a_predictor]

		#print "price=%s, pred_result=%s" % (current_price,prediction_result)

		if prediction_result>1:
			return LONG
		else:
			return SHORT

