 
import pandas as pd
import datetime
import numpy as np
import plotly as pl
import plotly.graph_objs as go
import matplotlib.pyplot as plt
import math
import scipy
import random
import statistics 


import datetime 





class CoreMath:
    
    def __init__(self, base_df, params=None):
        default_params = {
            'dataType':'ohcl',
            'action': None,
            'actionOptions':{}
        }
        self.base_df=base_df.reset_index(drop=True)
        self.params=params if params is not None else default_params
        if self.params['dataType']=='ohcl':
            self.col=self.base_df[self.params['actionOptions']['valueType']]
        elif self.params['dataType']=='series':
            self.col=self.base_df
        self.ans=self.getAns()
        
    
    def getAns(self):
        ans=None
        
        if self.params['action']=='findExt':
            ans = self.getExtremumValue()
        elif self.params['action']=='findMean':
            ans = self.getMeanValue()
        elif self.params['action']=='findSTD':
            ans=self.getSTD()
        
            
        return ans
    
    
    def getExtremumValue(self):
        ans=None
        '''
        actionOptions:
            'extremumtype':
                'min'
                'max'
            'valueType':
                'open'
                'close'
                'high'
                'low'
        '''
        if self.params['actionOptions']['extremumtype']=='max':
            ans=max(self.col)
            
        if self.params['actionOptions']['extremumtype']=='min':
            ans=min(self.col)

            
        return ans
     
        
    def getMeanValue(self):
        '''
        actionOptions:
            'MeanType':
                'MA'
                'SMA'
                'EMA'
                'WMA'
                --'SMMA'
            'valueType':
                'open'
                'close'
                'high'
                'low'
            'window'
            'span'
            'weights'
        '''
        ans=None
        if self.params['actionOptions']['MeanType']=='MA':
            ans = self.col.mean()
        if self.params['actionOptions']['MeanType']=='SMA':
            ans=np.convolve(self.col, np.ones(self.params['actionOptions']['window']), 'valid') / self.params['actionOptions']['window']
            #ans=self.col.rolling(window=self.params['actionOptions']['window']).mean().to_list()
            
        if self.params['actionOptions']['MeanType']=='EMA':
            ans=self.col.ewm(span=self.params['actionOptions']['span'], adjust=False).mean().to_list()
        if self.params['actionOptions']['MeanType']=='WMA':
            try:
                weights=self.params['actionOptions']['weights']
            except KeyError:
                weights=np.arange(1,self.params['actionOptions']['window']+1)
            ans=self.col.rolling(window=self.params['actionOptions']['window']).apply(lambda x: np.sum(weights*x) / weights.sum(), raw=False).to_list()

        
        
        return(ans)
    
    def getSTD(self):
        '''
        actionOptions:
            window
        
        
        
        
        
        '''
        
        ans=None


        try:
            window=self.params['actionOptions']['window']
            ans=np.asarray([])
            for i in range(len(self.col)-window+1):
                ans=np.append(ans,np.std(self.col[i:i+window], ddof=1))
            
        except:
            #window = len(self.col)
            ans=np.std(self.col, ddof=1)

        return ans
        