from abc import ABC, abstractmethod import datetime class Position(ABC): def __init__(self, fee, nolog=False): self.nUnits = 0 # the position size in token units (in the price denominating unit) self.fee = fee # fee for opening or closing a position (aka performing a swap) self.open = False self.ts_opened = None self.ts_closed = None self.opened_at_price = None self.closed_at_price = None self.performance = 0 self.nolog = nolog def set_position_open(self, nUnits, current_price, current_reg_fun_vals: list): self.open = True self.ts_opened = datetime.datetime.now() self.opened_at_price = current_price self.nUnits = nUnits * (1 - self.fee) self.log_msg(self.to_str() + "| Position opened. nUnits: " + str(round(self.nUnits, 4)) + " opened at price: " + str(round(self.opened_at_price, 4))) self.set_tp_io(current_price, current_reg_fun_vals) def set_position_closed(self, current_price): self.ts_closed = datetime.datetime.now() self.closed_at_price = current_price self.nUnits = self.nUnits * self.closed_at_price/self.opened_at_price * (1-self.fee) self.performance = (current_price/self.opened_at_price - 1) * 100 self.open = False @abstractmethod def update_position(self): """ check if position state needs to be changed. E.g. set to closed """ # returns nUnits (size of position) if position is closed pass def get_performance(self): return self.performance def get_unrealized_profit(self, current_price): return (current_price / self.opened_at_price - 1) * 100 def to_str(self): return "POS_" + self.ts_opened.strftime("%Y%m%d%H%M%S%f") def log_msg(self, msg): """ write message to log """ if self.nolog: pass else: print(msg)