import pandas as pd
import numpy as np
import time
from datetime import datetime, timedelta, timezone
import tpqoa

class Trader(tpqoa.tpqoa):
    
    def __init__(self,config_file, instrument, period, window, units):
        super().__init__(config_file)
        self.instrument = instrument
        self.period=period
        self.tickData = pd.DataFrame()
        self.rawData = None 
        self.ultimoPeriodo = None 
        self.data = None
        self.units = units
        self.posizione = 0
        self.profits = [] # lista dei profitti
        
        ########################## STRATEGY SPECIFIC ATTRIBUTES ##############################
        self.window = window
        
    def getMostRecent(self, days=5): 
        '''questo metodo scarica i dati FINO ad adesso'''
        while True:
            now = datetime.now(timezone.utc)
            now = now - timedelta(microseconds = now.microsecond) # pay attention, microseconds and then microsecond (singular!!!)
            yesterday = now - timedelta(days= days) # lo chiamo YESTERDAY, ma è l'inizio del periodo da scaricare
            df = self.get_history(instrument = self.instrument, start = str(yesterday)[:-6], end = str(now)[:-6],
                        granularity= "S5", price="M", localize=False)["c"].to_frame() 
                        # scarico a 5secondi, il che vuol dire che period non può essere più corto!
            df.rename(columns={"c":self.instrument},inplace=True)
            self.rawData = df.resample(self.period, label="right").last().dropna().iloc[:-1]
            self.ultimoPeriodo = self.rawData.index[-1]
            if pd.to_datetime(datetime.now(timezone.utc)) - self.ultimoPeriodo < pd.to_timedelta(self.period):
                break
            else:
                time.sleep(2)
    
    def on_success(self, time, bid, ask):
        print(self.ticks, end=" ")
        tickCorrente = pd.to_datetime(time)
        df = pd.DataFrame({self.instrument:(ask+bid)/2}, index=[tickCorrente])
        self.tickData=pd.concat((self.tickData,df),axis=0)
        if tickCorrente - self.ultimoPeriodo > pd.to_timedelta(self.period):
            self.resampleJoin()
            self.defineStrategy()
            self.executeTrade()
    
    def resampleJoin(self):
        self.rawData=pd.concat((self.rawData,self.tickData.resample(self.period,label="right").last().ffill().iloc[:-1] ),axis=0)
        self.tickData = self.tickData.iloc[-1:] 
        self.ultimoPeriodo = self.rawData.index[-1] 
        
    def defineStrategy(self):
        df = self.rawData.copy()
        df["logRet"]=np.log(df[self.instrument] / df[self.instrument].shift(1))
        df["posizione"]= - np.sign(df.logRet.rolling(self.window).mean())
        self.data = df.copy()
        
    def executeTrade(self):
        if self.data.posizione.iloc[-1] == 1: # andiamo lunghi
            if self.posizione == 0:
                order = self.create_order(instrument = self.instrument, units = self.units, suppress=True, ret = True)
                self.report_trade(order,"VADO LUNGO") #NEW!
            elif self.posizione == -1:
                order = self.create_order(instrument = self.instrument, units = 2*self.units, suppress=True, ret = True)
                self.report_trade(order,"CHIUDO POSIZIONE CORTA E VADO LUNGO") #NEW!
            self.posizione=1
        elif self.data.posizione.iloc[-1] == -1: # andiamo corti
            if self.posizione == 0:
                order = self.create_order(instrument = self.instrument, units = -self.units, suppress=True, ret = True)
                self.report_trade(order,"VADO CORTO") #NEW!
            elif self.posizione == 1:
                order = self.create_order(instrument = self.instrument, units = -2*self.units, suppress=True, ret = True)
                self.report_trade(order,"CHIUDO POSIZIONE LUNGA E VADO CORTO") #NEW!
            self.posizione=-1
        elif self.data.posizione.iloc[-1] == 0: # andiamo neutri
            if self.posizione == 1:
                order = self.create_order(instrument = self.instrument, units = -self.units, suppress=True, ret = True)
                self.report_trade(order,"CHIUDO POSIZIONE LUNGA") #NEW!
            elif self.posizione == -1:
                order = self.create_order(instrument = self.instrument, units = self.units, suppress=True, ret = True)
                self.report_trade(order,"CHIUDO POSIZIONE CORTA") #NEW!
            self.posizione=0

    def report_trade(self,order,message):
        time=order["time"]
        units=order["units"]
        price=order["price"]
        pl=float(order["pl"]) # profit/loss
        self.profits.append(pl)
        cumpl=sum(self.profits)
        print("\n-------------------------------------------------")
        print(time,"|",message)
        print("quantita=",units,"| prezzo=",price,"| profit/loss=",pl,"| profitto totale=",cumpl)
        print("-------------------------------------------------")
        
    def stream_data(self,instrument=None, stop=None, ret=False, callback=None): # aggiungo un nuovo default per instrument!
        if instrument is None:
            instrument=self.instrument
        super().stream_data(instrument, stop, ret, callback)
        if self.posizione != 0:
            close_all=self.create_order(self.instrument, units=-self.posizione*self.units,suppress=True,ret=True)
            self.report_trade(close_all,"CHIUDO TUTTO")
            self.posizione=0

if __name__ == "__main__":
    myTrader = Trader("oandaMY.cfg","EUR_USD","1min", window=1, units=100000)
    print(datetime.now(timezone.utc))
    myTrader.getMostRecent()
    myTrader.stream_data(stop=150)
