from v2realbot.strategy.base import Strategy
from v2realbot.utils.utils import parse_alpaca_timestamp, ltp, AttributeDict,trunc,price2dec, zoneNY, print, json_serial, safe_get, get_tick, send_to_telegram, transform_data
from v2realbot.utils.tlog import tlog, tlog_exception
from v2realbot.enums.enums import Mode, Order, Account, RecordType, Followup
#from alpaca.trading.models import TradeUpdate
from  v2realbot.common.model import TradeUpdate
from v2realbot.common.PrescribedTradeModel import Trade, TradeDirection, TradeStatus
from alpaca.trading.enums import TradeEvent, OrderStatus
from v2realbot.indicators.indicators import ema
import orjson
from datetime import datetime
from rich import print as printanyway
from random import randrange
from alpaca.common.exceptions import APIError
import numpy as np
from threading import Event
from uuid import UUID, uuid4
from v2realbot.strategyblocks.indicators.indicators_hub import populate_all_indicators
from v2realbot.strategyblocks.activetrade.helpers import get_profit_target_price

class StrategyClassicSL(Strategy):
    """
    Base override file for Classic Stop-Loss startegy
    """
    def __init__(self, name: str, symbol: str, next: callable, init: callable, account: Account, mode: Mode = Mode.PAPER, stratvars: AttributeDict = None, open_rush: int = 30, close_rush: int = 30, pe: Event = None, se: Event = None, runner_id: UUID = None, ilog_save: bool = False) -> None:
        super().__init__(name, symbol, next, init, account, mode, stratvars, open_rush, close_rush, pe, se, runner_id, ilog_save)

    #zkontroluje zda aktualni profit/loss - nedosahnul limit a pokud ano tak vypne strategii

    ##TODO zestručnit a dát pryč opakovací kód
    async def stop_when_max_profit_loss(self):
        self.state.ilog(e="CHECK MAX PROFIT")
        max_sum_profit_to_quit = safe_get(self.state.vars, "max_sum_profit_to_quit", None)
        max_sum_loss_to_quit = safe_get(self.state.vars, "max_sum_loss_to_quit", None)

        max_sum_profit_to_quit_rel = safe_get(self.state.vars, "max_sum_profit_to_quit_rel", None)
        max_sum_loss_to_quit_rel = safe_get(self.state.vars, "max_sum_loss_to_quit_rel", None)
        #load typ direktivy hard/soft cutoff
        hard_cutoff = safe_get(self.state.vars, "hard_cutoff", False)

        rel_profit  = round(float(np.sum(self.state.rel_profit_cum)),5)
        if max_sum_profit_to_quit_rel is not None:
            if rel_profit >= float(max_sum_profit_to_quit_rel):
                msg = f"QUITTING {hard_cutoff=} MAX SUM REL PROFIT REACHED {max_sum_profit_to_quit_rel=} {self.state.profit=} {rel_profit=} relprofits:{str(self.state.rel_profit_cum)}"
                printanyway(msg)
                self.state.ilog(e=msg)
                self.state.vars.pending = "max_sum_profit_to_quit_rel"
                if self.mode not in [Mode.BT, Mode.PREP]:
                    send_to_telegram(msg)
                if hard_cutoff:
                    self.hard_stop = True
                else:
                    self.soft_stop = True
                return True
        if max_sum_loss_to_quit_rel is not None:
            if rel_profit < 0 and rel_profit <= float(max_sum_loss_to_quit_rel):
                msg=f"QUITTING {hard_cutoff=} MAX SUM REL LOSS REACHED {max_sum_loss_to_quit_rel=} {self.state.profit=} {rel_profit=} relprofits:{str(self.state.rel_profit_cum)}"
                printanyway(msg)
                self.state.ilog(e=msg)
                self.state.vars.pending = "max_sum_loss_to_quit_rel"
                if self.mode not in [Mode.BT, Mode.PREP]:
                    send_to_telegram(msg)
                if hard_cutoff:
                    self.hard_stop = True
                else:
                    self.soft_stop = True
                return True

        if max_sum_profit_to_quit is not None:
            if float(self.state.profit) >= float(max_sum_profit_to_quit):
                msg = f"QUITTING {hard_cutoff=} MAX SUM ABS PROFIT REACHED {max_sum_profit_to_quit=} {self.state.profit=} {rel_profit=} relprofits:{str(self.state.rel_profit_cum)}"
                printanyway(msg)
                self.state.ilog(e=msg)
                self.state.vars.pending = "max_sum_profit_to_quit"
                if self.mode not in [Mode.BT, Mode.PREP]:
                    send_to_telegram(msg)
                if hard_cutoff:
                    self.hard_stop = True
                else:
                    self.soft_stop = True
                return True
        if max_sum_loss_to_quit is not None:
            if float(self.state.profit) < 0 and float(self.state.profit) <= float(max_sum_loss_to_quit):
                msg = f"QUITTING {hard_cutoff=} MAX SUM ABS LOSS REACHED {max_sum_loss_to_quit=} {self.state.profit=} {rel_profit=} relprofits:{str(self.state.rel_profit_cum)}"
                printanyway(msg)
                self.state.ilog(e=msg)
                self.state.vars.pending = "max_sum_loss_to_quit"
                if self.mode not in [Mode.BT, Mode.PREP]:
                    send_to_telegram(msg)
                if hard_cutoff:
                    self.hard_stop = True
                else:
                    self.soft_stop = True
                return True

        return False

    async def add_followup(self, direction: TradeDirection, size: int, signal_name: str):
        trade_to_add = Trade(
            id=uuid4(),
            last_update=datetime.fromtimestamp(self.state.time).astimezone(zoneNY),
            status=TradeStatus.READY,
            size=size,
            generated_by=signal_name,
            direction=direction,
            entry_price=None,
            stoploss_value = None)

        self.state.vars.prescribedTrades.append(trade_to_add)
        
        self.state.vars.requested_followup = None

        self.state.ilog(e=f"FOLLOWUP {direction} added to prescr.trades {signal_name=} {size=}", trade=trade_to_add)

    async def orderUpdateBuy(self, data: TradeUpdate):
        o: Order = data.order
        signal_name = None
        ##nejak to vymyslet, aby se dal poslat cely Trade a serializoval se
        self.state.ilog(e="Příchozí BUY notif", msg=o.status, trade=transform_data(data, json_serial))

        if data.event == TradeEvent.FILL or data.event == TradeEvent.PARTIAL_FILL:

           #pokud jde o fill pred kterym je partail, muze se stat, ze uz budou vynulovany pozice, toto je pojistka
            #jde o uzavření short pozice - počítáme PROFIT
            if int(self.state.positions) < 0 or (int(self.state.positions) == 0 and self.state.wait_for_fill is not None):

                if data.event == TradeEvent.PARTIAL_FILL and self.state.wait_for_fill is None:
                    #timto si oznacime, ze po partialu s vlivem na PROFIT musime cekat na FILL a zaroven ukladame prum cenu, kterou potrebujeme na vypocet profitu u fillu
                    self.state.wait_for_fill = float(self.state.avgp)

                #PROFIT pocitame z TradeUpdate.price a TradeUpdate.qty - aktualne provedene mnozstvi a cena
                #naklady vypocteme z prumerne ceny, kterou mame v pozicich
                bought_amount = data.qty * data.price
                #podle prumerne vstupni ceny, kolik stalo toto mnozstvi
                if float(self.state.avgp) > 0:
                    vstup_cena = float(self.state.avgp)
                elif float(self.state.avgp) == 0 and self.state.wait_for_fill is not None:
                    vstup_cena = float(self.state.wait_for_fill)
                else:
                    vstup_cena = 0

                avg_costs = vstup_cena * float(data.qty)
                
                if avg_costs == 0:
                    self.state.ilog(e="ERR: Nemame naklady na PROFIT, AVGP je nula. Zaznamenano jako 0", msg="naklady=utrzena cena. TBD opravit.")
                    avg_costs = bought_amount

                trade_profit = round((avg_costs-bought_amount),2)
                self.state.profit += trade_profit

                rel_profit = 0
                #spoctene celkovy relativni profit za trade v procentech ((trade_profit/vstup_naklady)*100)
                if vstup_cena != 0 and int(data.order.qty) != 0:
                    rel_profit = round((trade_profit / (vstup_cena * float(data.order.qty))) * 100,5)

                #pokud jde o finalni FILL - pridame do pole tento celkovy relativnich profit (ze ktereho se pocita kumulativni relativni profit)
                rel_profit_cum_calculated = 0
                partial_exit = False
                partial_last = False
                if data.event == TradeEvent.FILL:
                    #jde o partial EXIT dvááme si rel.profit do docasne promenne, po poslednim exitu z nich vypocteme skutecny rel.profit
                    if data.position_qty != 0:
                        self.state.docasny_rel_profit.append(rel_profit)
                        partial_exit = True
                    else:
                        #jde o posledni z PARTIAL EXITU tzn.data.position_qty == 0
                        if len(self.state.docasny_rel_profit) > 0:
                            #pricteme aktualni rel profit
                            self.state.docasny_rel_profit.append(rel_profit)
                            #a z rel profitu tohoto tradu vypocteme prumer, ktery teprve ulozime
                            rel_profit = round(np.mean(self.state.docasny_rel_profit),5)
                            self.state.docasny_rel_profit = []
                            partial_last = True

                        self.state.rel_profit_cum.append(rel_profit)
                        rel_profit_cum_calculated = round(np.sum(self.state.rel_profit_cum),5)

                        #pro martingale updatujeme loss_series_cnt
                        self.state.vars["transferables"]["martingale"]["cont_loss_series_cnt"] = 0 if rel_profit > 0 else self.state.vars["transferables"]["martingale"]["cont_loss_series_cnt"]+1
                        self.state.ilog(lvl=1, e=f"update cont_loss_series_cnt na {self.state.vars['transferables']['martingale']['cont_loss_series_cnt']}")

                self.state.ilog(e=f"BUY notif - SHORT PROFIT: {partial_exit=} {partial_last=} {round(float(trade_profit),3)} celkem:{round(float(self.state.profit),3)} rel:{float(rel_profit)} rel_cum:{round(rel_profit_cum_calculated,7)}", msg=str(data.event), rel_profit_cum=str(self.state.rel_profit_cum), bought_amount=bought_amount, avg_costs=avg_costs, trade_qty=data.qty, trade_price=data.price, orderid=str(data.order.id))

                #zapsat profit do prescr.trades
                for trade in self.state.vars.prescribedTrades:
                    if trade.id == self.state.vars.pending:
                        trade.last_update = datetime.fromtimestamp(self.state.time).astimezone(zoneNY)
                        trade.profit += trade_profit
                        #pro ulozeni do tradeData scitame vsechen zisk z tohoto tradu (kvuli partialum)
                        trade_profit = trade.profit
                        trade.profit_sum = self.state.profit
                        trade.rel_profit = rel_profit
                        trade.rel_profit_cum = rel_profit_cum_calculated
                        signal_name = trade.generated_by

                        #Pokud FILL uzaviral celou pozici - uzavreme prescribed trade
                        if data.event == TradeEvent.FILL and data.position_qty == 0:
                            trade.status = TradeStatus.CLOSED
                            trade.exit_time = datetime.fromtimestamp(self.state.time).astimezone(zoneNY)
                        break

                if data.event == TradeEvent.FILL:
                    #mazeme self.state.
                    self.state.wait_for_fill = None
                    #zapsat update profitu do tradeList
                    for tradeData in self.state.tradeList:
                        if tradeData.execution_id == data.execution_id:
                            #pridat jako attribut, aby proslo i na LIVE a PAPPER, kde se bere TradeUpdate z Alpaca
                            setattr(tradeData, "profit", trade_profit)
                            setattr(tradeData, "profit_sum", self.state.profit)
                            setattr(tradeData, "signal_name", signal_name)
                            setattr(tradeData, "prescribed_trade_id", self.state.vars.pending)
                            #self.state.ilog(f"updatnut tradeList o profit", tradeData=orjson.loads(orjson.dumps(tradeData, default=json_serial, option=orjson.OPT_PASSTHROUGH_DATETIME)))
                            setattr(tradeData, "rel_profit", rel_profit)
                            setattr(tradeData, "rel_profit_cum", rel_profit_cum_calculated)

                #test na maximalni profit/loss, pokud vypiname pak uz nedelame pripdany reverzal
                #kontrolu na max loss provadime az u FILLu, kdy je znama celkova castka
                if data.event == TradeEvent.FILL and await self.stop_when_max_profit_loss() is False:

                    #pIF REVERSAL REQUIRED - reverse position is added to prescr.Trades with same signal name
                    #jen při celém FILLU
                    if data.event == TradeEvent.FILL and self.state.vars.requested_followup is not None:
                            if self.state.vars.requested_followup == Followup.REVERSE:
                                await self.add_followup(direction=TradeDirection.LONG, size=o.qty, signal_name=signal_name)
                            elif self.state.vars.requested_followup == Followup.ADD:
                                #zatim stejna SIZE
                                await self.add_followup(direction=TradeDirection.SHORT, size=o.qty, signal_name=signal_name)
            else:
                #zjistime nazev signalu a updatneme do tradeListu - abychom meli svazano
                for trade in self.state.vars.prescribedTrades:
                    if trade.id == self.state.vars.pending:
                        signal_name = trade.generated_by
                        #zapiseme entry_time (jen pokud to neni partial add) - tzn. jen poprvé
                        if data.event == TradeEvent.FILL and trade.entry_time is None:
                            trade.entry_time = datetime.fromtimestamp(self.state.time).astimezone(zoneNY)

                #zapsat do tradeList
                for tradeData in self.state.tradeList:
                    if tradeData.execution_id == data.execution_id:
                        setattr(tradeData, "signal_name", signal_name)
                        setattr(tradeData, "prescribed_trade_id", self.state.vars.pending)

                self.state.ilog(e="BUY: Jde o LONG nakuú nepocitame profit zatim")

                if data.event == TradeEvent.FILL:
                    #zapisujeme last entry price
                    self.state.last_entry_price["long"] = data.price

                    #pokud neni nastaveno goal_price tak vyplnujeme defaultem
                    if self.state.vars.activeTrade.goal_price is None:
                        dat = dict(close=data.price)
                        self.state.vars.activeTrade.goal_price = get_profit_target_price(self.state, dat, TradeDirection.LONG)

            #ic("vstupujeme do orderupdatebuy")
            print(data)
            #dostavame zde i celkové akutální množství - ukládáme
            self.state.positions = data.position_qty
            self.state.avgp, self.state.positions = self.state.interface.pos()

        if o.status == OrderStatus.FILLED or o.status == OrderStatus.CANCELED:
            #davame pryc pending
            self.state.vars.pending = None


    async def orderUpdateSell(self, data: TradeUpdate): 
        
        self.state.ilog(e="Příchozí SELL notif", msg=data.order.status, trade=transform_data(data, json_serial))

        #naklady vypocteme z prumerne ceny, kterou mame v pozicich
        if data.event == TradeEvent.FILL or data.event == TradeEvent.PARTIAL_FILL:            

           #pokud jde o fill pred kterym je partail, muze se stat, ze uz budou vynulovany pozice, toto je pojistka
           #jde o uzavření long pozice - počítáme PROFIT
            if int(self.state.positions) > 0 or (int(self.state.positions) == 0 and self.state.wait_for_fill is not None):

                if data.event == TradeEvent.PARTIAL_FILL and self.state.wait_for_fill is None:
                    #timto si oznacime, ze po partialu s vlivem na PROFIT musime cekat na FILL a zaroven ukladame prum cenu, kterou potrebujeme na vypocet profitu u fillu
                    self.state.wait_for_fill = float(self.state.avgp)

                #PROFIT pocitame z TradeUpdate.price a TradeUpdate.qty - aktualne provedene mnozstvi a cena
                #naklady vypocteme z prumerne ceny, kterou mame v pozicich
                sold_amount = data.qty * data.price
                if float(self.state.avgp) > 0:
                    vstup_cena = float(self.state.avgp)
                elif float(self.state.avgp) == 0 and self.state.wait_for_fill is not None:
                    vstup_cena = float(self.state.wait_for_fill)
                else:
                    vstup_cena = 0

                #podle prumerne ceny, kolik stalo toto mnozstvi
                avg_costs = vstup_cena * float(data.qty)
 
                if avg_costs == 0:
                    self.state.ilog(e="ERR: Nemame naklady na PROFIT, AVGP je nula. Zaznamenano jako 0", msg="naklady=utrzena cena. TBD opravit.")
                    avg_costs = sold_amount
                
                trade_profit = round((sold_amount - avg_costs),2)
                self.state.profit += trade_profit

                rel_profit = 0
                #spoctene celkovy relativni profit za trade v procentech ((trade_profit/vstup_naklady)*100)
                if vstup_cena != 0 and data.order.qty != 0:
                    rel_profit = round((trade_profit / (vstup_cena * float(data.order.qty))) * 100,5)

                rel_profit_cum_calculated = 0
                partial_exit = False
                partial_last = False
                if data.event == TradeEvent.FILL:
                    #jde o partial EXIT dvááme si rel.profit do docasne promenne, po poslednim exitu z nich vypocteme skutecny rel.profit
                    if data.position_qty != 0:
                        self.state.docasny_rel_profit.append(rel_profit)
                        partial_exit = True
                    else:
                        #jde o posledni z PARTIAL EXITU tzn.data.position_qty == 0
                        if len(self.state.docasny_rel_profit) > 0:
                            #pricteme aktualni rel profit
                            self.state.docasny_rel_profit.append(rel_profit)
                            #a z rel profitu tohoto tradu vypocteme prumer, ktery teprve ulozime
                            rel_profit = round(np.mean(self.state.docasny_rel_profit),5)
                            self.state.docasny_rel_profit = []
                            partial_last = True

                        self.state.rel_profit_cum.append(rel_profit)
                        rel_profit_cum_calculated = round(np.sum(self.state.rel_profit_cum),5)

                        #pro martingale updatujeme loss_series_cnt
                        self.state.vars["transferables"]["martingale"]["cont_loss_series_cnt"] = 0 if rel_profit > 0 else self.state.vars["transferables"]["martingale"]["cont_loss_series_cnt"]+1
                        self.state.ilog(lvl=1, e=f"update cont_loss_series_cnt na {self.state.vars['transferables']['martingale']['cont_loss_series_cnt']}")

                self.state.ilog(e=f"SELL notif - LONG PROFIT {partial_exit=} {partial_last=}:{round(float(trade_profit),3)} celkem:{round(float(self.state.profit),3)} rel:{float(rel_profit)} rel_cum:{round(rel_profit_cum_calculated,7)}", msg=str(data.event), rel_profit_cum = str(self.state.rel_profit_cum), sold_amount=sold_amount, avg_costs=avg_costs, trade_qty=data.qty, trade_price=data.price, orderid=str(data.order.id))

                #zapsat profit do prescr.trades
                for trade in self.state.vars.prescribedTrades:
                    if trade.id == self.state.vars.pending:
                        trade.last_update = datetime.fromtimestamp(self.state.time).astimezone(zoneNY)
                        trade.profit += trade_profit
                        #pro ulozeni do tradeData scitame vsechen zisk z tohoto tradu (kvuli partialum)
                        trade_profit = trade.profit
                        trade.profit_sum = self.state.profit
                        trade.rel_profit = rel_profit
                        trade.rel_profit_cum = rel_profit_cum_calculated
                        signal_name = trade.generated_by
                        #Pokud FILL uzaviral celou pozici - uzavreme prescribed trade
                        if data.event == TradeEvent.FILL and data.position_qty == 0:
                            trade.status = TradeStatus.CLOSED
                            trade.exit_time = datetime.fromtimestamp(self.state.time).astimezone(zoneNY)
                        break

                if data.event == TradeEvent.FILL:
                    #mazeme self.state.
                    self.state.wait_for_fill = None
                    #zapsat update profitu do tradeList
                    for tradeData in self.state.tradeList:
                        if tradeData.execution_id == data.execution_id:
                            #pridat jako attribut, aby proslo i na LIVE a PAPPER, kde se bere TradeUpdate z Alpaca
                            setattr(tradeData, "profit", trade_profit)
                            setattr(tradeData, "profit_sum", self.state.profit)
                            setattr(tradeData, "signal_name", signal_name)
                            setattr(tradeData, "prescribed_trade_id", self.state.vars.pending)
                            #self.state.ilog(f"updatnut tradeList o profi {str(tradeData)}")
                            setattr(tradeData, "rel_profit", rel_profit)
                            setattr(tradeData, "rel_profit_cum", rel_profit_cum_calculated)
                            #sem nejspis update skutecne vstupni ceny (celk.mnozstvi(order.qty) a avg_costs), to same i druhy smer

                #kontrolu na max loss provadime az u FILLu, kdy je znama celkova castka
                if data.event == TradeEvent.FILL and await self.stop_when_max_profit_loss() is False:

                    #IF REVERSAL REQUIRED - reverse position is added to prescr.Trades with same signal name
                    if data.event == TradeEvent.FILL and self.state.vars.requested_followup is not None:
                            if self.state.vars.requested_followup == Followup.REVERSE:
                                await self.add_followup(direction=TradeDirection.SHORT, size=data.order.qty, signal_name=signal_name)
                            elif self.state.vars.requested_followup == Followup.ADD:
                                #zatim stejna SIZE
                                await self.add_followup(direction=TradeDirection.LONG, size=data.order.qty, signal_name=signal_name)                            

            else:
                #zjistime nazev signalu a updatneme do tradeListu - abychom meli svazano
                for trade in self.state.vars.prescribedTrades:
                    if trade.id == self.state.vars.pending:
                        signal_name = trade.generated_by
                        #zapiseme entry_time (jen pokud to neni partial add) - tzn. jen poprvé
                        if data.event == TradeEvent.FILL and trade.entry_time is None:
                            trade.entry_time = datetime.fromtimestamp(self.state.time).astimezone(zoneNY)

                #zapsat update profitu do tradeList
                for tradeData in self.state.tradeList:
                    if tradeData.execution_id == data.execution_id:
                        setattr(tradeData, "signal_name", signal_name)
                        setattr(tradeData, "prescribed_trade_id", self.state.vars.pending)

                self.state.ilog(e="SELL: Jde o SHORT nepocitame profit zatim")

                if data.event == TradeEvent.FILL:
                    #zapisujeme last entry price
                    self.state.last_entry_price["short"] = data.price
                    #pokud neni nastaveno goal_price tak vyplnujeme defaultem
                    if self.state.vars.activeTrade.goal_price is None:
                        dat = dict(close=data.price)
                        self.state.vars.activeTrade.goal_price = get_profit_target_price(self.state, dat, TradeDirection.SHORT)
                    #sem v budoucnu dat i update SL
                    #if self.state.vars.activeTrade.stoploss_value is None:


            #update pozic, v trade update je i pocet zbylych pozic
            old_avgp = self.state.avgp
            old_pos = self.state.positions
            self.state.positions = int(data.position_qty)
            if int(data.position_qty) == 0:
                self.state.avgp = 0

            self.state.ilog(e="SELL notifikace "+str(data.order.status), msg="update pozic", old_avgp=old_avgp, old_pos=old_pos, avgp=self.state.avgp, pos=self.state.positions, orderid=str(data.order.id))
            #self.state.avgp, self.state.positions = self.interface.pos()

        if data.event == TradeEvent.FILL or data.event == TradeEvent.CANCELED:
            print("Příchozí SELL notifikace - complete FILL nebo CANCEL", data.event)
            self.state.vars.pending = None
            a,p = self.interface.pos()
            #pri chybe api nechavame puvodni hodnoty
            if a != -1:
                self.state.avgp, self.state.positions = a,p
            else: self.state.ilog(e=f"Chyba pri dotažení self.interface.pos() {a}")
            #ic(self.state.avgp, self.state.positions)

    #this parent method is called by strategy just once before waiting for first data
    def strat_init(self):
        #ic("strat INI function")
        #lets connect method overrides
        self.state.buy = self.buy
        self.state.sell = self.sell

        self.init(self.state)

    def call_next(self, item):
        #MAIN INDICATORS
        populate_all_indicators(item, self.state)
        
        #pro přípravu dat next nevoláme
        if self.mode == Mode.PREP or self.soft_stop:
            return
        else:
            self.next(item, self.state)

    #overidden methods
    # pouziva se pri vstupu long nebo exitu short
    # osetrit uzavreni s vice nez mam
    def buy(self, size = None, repeat: bool = False):
        print("overriden buy method")
        if size is None:
            sizer = self.state.vars.chunk
        else:
            sizer = size
        #jde o uzavreni short pozice
        if int(self.state.positions) < 0 and (int(self.state.positions) + int(sizer)) > 0:
            self.state.ilog(e="buy nelze nakoupit vic nez shortuji", positions=self.state.positions, size=size)
            printanyway("buy nelze nakoupit vic nez shortuji") 
            return -2

        if int(self.state.positions) >= self.state.vars.maxpozic:
            self.state.ilog(e="buy Maxim mnozstvi naplneno", positions=self.state.positions)
            printanyway("max mnostvi naplneno")
            return 0

        self.state.blockbuy = 1
        self.state.vars.lastbuyindex = self.state.bars['index'][-1]
        #self.state.ilog(e="send MARKET buy to if", msg="S:"+str(size), ltp=self.state.interface.get_last_price(self.state.symbol))
        self.state.ilog(e="send MARKET buy to if", msg="S:"+str(size), ltp=self.state.bars['close'][-1])
        return self.state.interface.buy(size=sizer)

    #overidden methods
    # pouziva se pri vstupu short nebo exitu long
    def sell(self, size = None, repeat: bool = False):
        print("overriden sell method")
        if size is None:
            size = abs(int(self.state.positions))

        #jde o uzavreni long pozice
        if int(self.state.positions) > 0 and (int(self.state.positions) - int(size)) < 0:
            self.state.ilog(e="nelze prodat vic nez longuji", positions=self.state.positions, size=size)
            printanyway("nelze prodat vic nez longuji") 
            return -2

        #pokud shortuji a mam max pozic
        if int(self.state.positions) < 0 and abs(int(self.state.positions)) >= self.state.vars.maxpozic:
            self.state.ilog(e="short - Maxim mnozstvi naplneno", positions=self.state.positions, size=size)
            printanyway("short - Maxim mnozstvi naplneno") 
            return 0

        #self.state.blocksell = 1
        #self.state.vars.lastbuyindex = self.state.bars['index'][-1]
        #self.state.ilog(e="send MARKET SELL to if", msg="S:"+str(size), ltp=self.state.interface.get_last_price(self.state.symbol))
        self.state.ilog(e="send MARKET SELL to if", msg="S:"+str(size), ltp=self.state.bars['close'][-1])
        return self.state.interface.sell(size=size)