# -*-mode: python; py-indent-offset: 4; indent-tabs-mode: nil; encoding: utf-8-dos; coding: utf-8 -*-

"""
"""

import sys
import datetime
import pandas

from OpenTrader.Omlettes.Recipe import Recipe

class SMARecipe(Recipe):
        
    #? should oOm be required?
    def __init__(self, oOm=None, oFd=sys.stdout):
        Recipe.__init__(self, oOm, oFd)
        self.__fVersion__ = 1.0
        self.sIniFile = 'SMARecipe.ini'
        self.sFile = __file__

    # make this a property>
    def oEnsureConfigObj(self):
        """
        oEnsureConfigObj ensures that the .ini file has been read.
        For each recipe, an .ini file is now required and is relied on.
        It's only read once, and is stored as self.oConfigObj
        """
        if self.oConfigObj is not None:
            return self.oConfigObj
        self.vReadIniFile()
        assert self.oConfigObj is not None
        return self.oConfigObj
    
    def dMakeIngredients(self, dFeeds):
        """
        dMakeIngredients takes a dictionary of feeds dFeeds
        with at least one key from lRequiredFeeds to work on.
        It returns a dictionary of ingredients with the keys in lRequiredIngredients
        and a copy of the config  that it used as the key dIngredientsConfig.
        """
        oC = self.oEnsureConfigObj()
        assert oC is not None
        iLongMa = oC['rLongMa']['iLongMa']
        iShortMa = oC['rShortMa']['iShortMa']
        bUseTalib = oC['rShortMa']['bUseTalib']

        self.vCheckRequiredFeeds(dFeeds)
        mFeedOhlc = dFeeds['mFeedOhlc']
        
        iBeginValid = max(iLongMa, iShortMa)-1
        iEndOhlc = len(mFeedOhlc)

        if bUseTalib:
            import talib
            aShortMA = talib.SMA(mFeedOhlc.O.values, timeperiod=iShortMa)
            aLongMA = talib.SMA(mFeedOhlc.O.values, timeperiod=iLongMa)
            rShortMa = pandas.Series(aShortMA, name='O',
                                     index=mFeedOhlc.O.index)
            rLongMa = pandas.Series(aLongMA, name='O',
                                    index=mFeedOhlc.O.index)
        else:
            rShortMa = pandas.rolling_mean(mFeedOhlc.O, iShortMa)
            rLongMa = pandas.rolling_mean(mFeedOhlc.O, iLongMa)

        rShortMa = rShortMa[iBeginValid:]
        rLongMa = rLongMa[iBeginValid:]
        mOhlc = mFeedOhlc[iBeginValid:]
        self.oOm.vAppendHdf('recipe/ingredients/rShortMa', rShortMa)
        self.oOm.vAppendHdf('recipe/ingredients/rLongMa', rLongMa)
        self.dIngredients = dict(rShortMa=rShortMa, rLongMa=rLongMa,
                                 mOhlc=mOhlc,
                                 dIngredientsConfig=dict(oC))
        return self.dIngredients
    
    def dApplyRecipe(self):
        """dApplyRecipe
        returns a dictionary with keys rBuy, rCover, rSell, rShort,
        which are pandas timeseries 
        and a copy of the dDishesParams.
        """
        #? copy this
        dDishesParams = self.dIngredients
        self.vCheckRequiredDishes(dDishesParams)
        rShortMa = dDishesParams['rShortMa']
        rLongMa = dDishesParams['rLongMa']
        
        assert isinstance(rShortMa, pandas.Series) and len(rShortMa)
        assert isinstance(rLongMa, pandas.Series) and len(rLongMa)

        self.oFd.write('INFO: Data MA length %d\n' % len(rShortMa))
        self.oFd.write('INFO: Date from: %s to: %s\n' % ( str(rShortMa.index[0]), str(rShortMa.index[-1]),))

        rBuy = rCover = (rShortMa > rLongMa) & (rShortMa.shift() < rLongMa.shift())  # ma cross up
        rSell = rShort = (rShortMa < rLongMa) & (rShortMa.shift() > rLongMa.shift())  # ma cross down
        # maybe one day
        dDishesParams = dict()
        return dict(rBuy=rBuy, rCover=rCover, rSell=rSell, rShort=rShort,
                    dDishesParams=dDishesParams)