added metadata to event. refactored function names and order in classes
This commit is contained in:
parent
a7b1d05029
commit
2d7307a038
@ -58,13 +58,17 @@ class Ticker:
|
|||||||
|
|
||||||
|
|
||||||
class Event:
|
class Event:
|
||||||
def __init__(self, kind: EventKind, tick: int) -> None:
|
def __init__(self, kind: EventKind, tick: int, metadata: Dict = None) -> None:
|
||||||
self.kind: EventKind = kind
|
self.kind: EventKind = kind
|
||||||
self.tick: int = tick
|
self.tick: int = tick
|
||||||
|
self.metadata = metadata
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
return f"{self.kind.name} @ Tick {self.tick}"
|
return f"{self.kind.name} @ Tick {self.tick}"
|
||||||
|
|
||||||
|
def has_metadata(self) -> bool:
|
||||||
|
return self.metadata is not None
|
||||||
|
|
||||||
|
|
||||||
class PositionWrapper:
|
class PositionWrapper:
|
||||||
def __init__(self, position: Position):
|
def __init__(self, position: Position):
|
||||||
@ -99,17 +103,10 @@ class SymbolStatus:
|
|||||||
self.current_tick: int = 1
|
self.current_tick: int = 1
|
||||||
self.strategy: Strategy = strategy
|
self.strategy: Strategy = strategy
|
||||||
|
|
||||||
def last_events(self, n) -> List[Event]:
|
def add_order(self, order: Order):
|
||||||
return self.events[-n:]
|
if self.strategy:
|
||||||
|
self.strategy.order_on_new_tick(order, self)
|
||||||
def last_positions(self) -> List[PositionWrapper]:
|
__add_to_dict_list__(self.orders, self.current_tick, order)
|
||||||
return self.positions[self.current_tick]
|
|
||||||
|
|
||||||
def all_ticks(self) -> List[int]:
|
|
||||||
return [x for x in range(1, self.current_tick + 1)]
|
|
||||||
|
|
||||||
def all_prices(self) -> List[float]:
|
|
||||||
return list(map(lambda x: self.prices[x], range(1, self.current_tick + 1)))
|
|
||||||
|
|
||||||
# Applies strategy and adds position to list
|
# Applies strategy and adds position to list
|
||||||
async def add_position(self, position: Position):
|
async def add_position(self, position: Position):
|
||||||
@ -119,10 +116,17 @@ class SymbolStatus:
|
|||||||
await self.__apply_strategy_to_position__(pw)
|
await self.__apply_strategy_to_position__(pw)
|
||||||
__add_to_dict_list__(self.positions, self.current_tick, pw)
|
__add_to_dict_list__(self.positions, self.current_tick, pw)
|
||||||
|
|
||||||
def add_order(self, order: Order):
|
def all_prices(self) -> List[float]:
|
||||||
if self.strategy:
|
return list(map(lambda x: self.prices[x], range(1, self.current_tick + 1)))
|
||||||
self.strategy.order_on_tick(order, self)
|
|
||||||
__add_to_dict_list__(self.orders, self.current_tick, order)
|
def all_ticks(self) -> List[int]:
|
||||||
|
return [x for x in range(1, self.current_tick + 1)]
|
||||||
|
|
||||||
|
def last_events(self, n) -> List[Event]:
|
||||||
|
return self.events[-n:]
|
||||||
|
|
||||||
|
def last_positions(self) -> List[PositionWrapper]:
|
||||||
|
return self.positions[self.current_tick]
|
||||||
|
|
||||||
def previous_position_w(self, pid: int) -> PositionWrapper:
|
def previous_position_w(self, pid: int) -> PositionWrapper:
|
||||||
if self.current_tick == 1:
|
if self.current_tick == 1:
|
||||||
@ -130,12 +134,18 @@ class SymbolStatus:
|
|||||||
|
|
||||||
return next(filter(lambda x: x.position.id == pid, self.positions[self.current_tick - 1]))
|
return next(filter(lambda x: x.position.id == pid, self.positions[self.current_tick - 1]))
|
||||||
|
|
||||||
|
def set_tick_price(self, tick, price):
|
||||||
|
self.prices[tick] = price
|
||||||
|
|
||||||
async def __add_event__(self, event: Event):
|
async def __add_event__(self, event: Event):
|
||||||
self.events.append(event)
|
self.events.append(event)
|
||||||
await self.eh.call_event(self, event)
|
await self.eh.call_event(self, event)
|
||||||
|
|
||||||
async def __apply_strategy_to_position__(self, pw: PositionWrapper):
|
async def __apply_strategy_to_position__(self, pw: PositionWrapper):
|
||||||
(new_state, events) = self.strategy.position_on_tick(pw.position, self)
|
if not self.strategy:
|
||||||
|
return
|
||||||
|
|
||||||
|
new_state, events = self.strategy.position_on_new_tick(pw.position, self)
|
||||||
|
|
||||||
if isinstance(new_state, PositionState):
|
if isinstance(new_state, PositionState):
|
||||||
await self.__update_position_state__(pw, new_state)
|
await self.__update_position_state__(pw, new_state)
|
||||||
@ -147,10 +157,7 @@ class SymbolStatus:
|
|||||||
|
|
||||||
async def __update_position_state__(self, pw: PositionWrapper, state: PositionState):
|
async def __update_position_state__(self, pw: PositionWrapper, state: PositionState):
|
||||||
pw.set_state(state)
|
pw.set_state(state)
|
||||||
await self.eh.call_state(self, pw)
|
await self.eh.call_position_state(self, pw)
|
||||||
|
|
||||||
def set_tick_price(self, tick, price):
|
|
||||||
self.prices[tick] = price
|
|
||||||
|
|
||||||
|
|
||||||
class Strategy:
|
class Strategy:
|
||||||
@ -158,14 +165,14 @@ class Strategy:
|
|||||||
Defines new position state and events after tick.
|
Defines new position state and events after tick.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def position_on_tick(self, position: Position, ss: SymbolStatus) -> (PositionState, List[Event]):
|
def position_on_new_tick(self, position: Position, ss: SymbolStatus) -> (PositionState, List[Event]):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Defines new order state and events after tick.
|
Defines new order state and events after tick.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def order_on_tick(self, order: Order, ss: SymbolStatus):
|
def order_on_new_tick(self, order: Order, ss: SymbolStatus):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@ -193,7 +200,7 @@ class EventHandler:
|
|||||||
else:
|
else:
|
||||||
h(event, status)
|
h(event, status)
|
||||||
|
|
||||||
async def call_state(self, status: SymbolStatus, pw: PositionWrapper):
|
async def call_position_state(self, status: SymbolStatus, pw: PositionWrapper):
|
||||||
state = pw.state
|
state = pw.state
|
||||||
|
|
||||||
if state in self.state_handlers:
|
if state in self.state_handlers:
|
||||||
@ -221,7 +228,7 @@ class EventHandler:
|
|||||||
|
|
||||||
return registerhandler
|
return registerhandler
|
||||||
|
|
||||||
def on_state(self, state: PositionState):
|
def on_position_state(self, state: PositionState):
|
||||||
def registerhandler(handler):
|
def registerhandler(handler):
|
||||||
if state in self.state_handlers:
|
if state in self.state_handlers:
|
||||||
self.state_handlers[state].append(handler)
|
self.state_handlers[state].append(handler)
|
||||||
@ -238,7 +245,7 @@ class EventHandler:
|
|||||||
|
|
||||||
return registerhandle
|
return registerhandle
|
||||||
|
|
||||||
def on_any_state(self):
|
def on_any_position_state(self):
|
||||||
def registerhandle(handler):
|
def registerhandle(handler):
|
||||||
self.any_state.append(handler)
|
self.any_state.append(handler)
|
||||||
return handler
|
return handler
|
||||||
|
26
strategy.py
26
strategy.py
@ -14,6 +14,7 @@ class Position(object):
|
|||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class SquaredTrailingStop:
|
class SquaredTrailingStop:
|
||||||
def __init__(self, p_min: Point, p_max: Point):
|
def __init__(self, p_min: Point, p_max: Point):
|
||||||
a = sympy.abc.a
|
a = sympy.abc.a
|
||||||
@ -24,8 +25,8 @@ class SquaredTrailingStop:
|
|||||||
self.p_max = p_max
|
self.p_max = p_max
|
||||||
|
|
||||||
e1 = 2 * a * (p_max.x + b)
|
e1 = 2 * a * (p_max.x + b)
|
||||||
e2 = a * (p_min.x + b)**2 + c - p_min.y
|
e2 = a * (p_min.x + b) ** 2 + c - p_min.y
|
||||||
e3 = a * (p_max.x + b)**2 + c - p_max.y
|
e3 = a * (p_max.x + b) ** 2 + c - p_max.y
|
||||||
|
|
||||||
s = solve([e1, e2, e3])[0]
|
s = solve([e1, e2, e3])[0]
|
||||||
|
|
||||||
@ -33,7 +34,7 @@ class SquaredTrailingStop:
|
|||||||
|
|
||||||
def y(self, x):
|
def y(self, x):
|
||||||
def inter_y(x):
|
def inter_y(x):
|
||||||
return self.a * (x + self.b)**2 + self.c
|
return self.a * (x + self.b) ** 2 + self.c
|
||||||
|
|
||||||
if x < self.p_min.x:
|
if x < self.p_min.x:
|
||||||
return self.p_min.y
|
return self.p_min.y
|
||||||
@ -47,6 +48,7 @@ class SquaredTrailingStop:
|
|||||||
return 0
|
return 0
|
||||||
return x - self.y(x)
|
return x - self.y(x)
|
||||||
|
|
||||||
|
|
||||||
class TrailingStopStrategy(Strategy):
|
class TrailingStopStrategy(Strategy):
|
||||||
BREAK_EVEN_PERC = TAKER_FEE
|
BREAK_EVEN_PERC = TAKER_FEE
|
||||||
MIN_PROFIT_PERC = BREAK_EVEN_PERC + 0.3
|
MIN_PROFIT_PERC = BREAK_EVEN_PERC + 0.3
|
||||||
@ -54,9 +56,9 @@ class TrailingStopStrategy(Strategy):
|
|||||||
MAX_LOSS_PERC = -3.75
|
MAX_LOSS_PERC = -3.75
|
||||||
OFFER_PERC = 0.005
|
OFFER_PERC = 0.005
|
||||||
|
|
||||||
TRAILING_STOP = SquaredTrailingStop(Point(MIN_PROFIT_PERC, MIN_PROFIT_PERC/3*2), Point(GOOD_PROFIT_PERC, 0.1))
|
TRAILING_STOP = SquaredTrailingStop(Point(MIN_PROFIT_PERC, MIN_PROFIT_PERC / 3 * 2), Point(GOOD_PROFIT_PERC, 0.1))
|
||||||
|
|
||||||
def position_on_tick(self, position: Position, ss: SymbolStatus) -> (PositionState, List[Event]):
|
def position_on_new_tick(self, position: Position, ss: SymbolStatus) -> (PositionState, List[Event]):
|
||||||
events = []
|
events = []
|
||||||
|
|
||||||
pl_perc = net_pl_percentage(position.profit_loss_percentage, TAKER_FEE)
|
pl_perc = net_pl_percentage(position.profit_loss_percentage, TAKER_FEE)
|
||||||
@ -77,17 +79,15 @@ class TrailingStopStrategy(Strategy):
|
|||||||
return state, events
|
return state, events
|
||||||
|
|
||||||
if state == PositionState.PROFIT:
|
if state == PositionState.PROFIT:
|
||||||
events.append(Event(EventKind.REACHED_GOOD_PROFIT, position.id, ss.current_tick))
|
events.append(Event(EventKind.REACHED_GOOD_PROFIT, ss.current_tick))
|
||||||
elif state == PositionState.MINIMUM_PROFIT:
|
elif state == PositionState.MINIMUM_PROFIT:
|
||||||
events.append(Event(EventKind.REACHED_MIN_PROFIT, position.id, ss.current_tick))
|
events.append(Event(EventKind.REACHED_MIN_PROFIT, ss.current_tick))
|
||||||
elif state == PositionState.BREAK_EVEN:
|
elif state == PositionState.BREAK_EVEN:
|
||||||
events.append(Event(EventKind.REACHED_BREAK_EVEN, position.id, ss.current_tick))
|
events.append(Event(EventKind.REACHED_BREAK_EVEN, ss.current_tick))
|
||||||
elif state == PositionState.LOSS:
|
elif state == PositionState.LOSS:
|
||||||
events.append(Event(EventKind.REACHED_LOSS, position.id, ss.current_tick))
|
events.append(Event(EventKind.REACHED_LOSS, ss.current_tick))
|
||||||
else:
|
else:
|
||||||
events.append(Event(EventKind.REACHED_MAX_LOSS, position.id, ss.current_tick))
|
events.append(Event(EventKind.REACHED_MAX_LOSS, ss.current_tick))
|
||||||
events.append(Event(EventKind.CLOSE_POSITION, position.id, ss.current_tick))
|
events.append(Event(EventKind.CLOSE_POSITION, ss.current_tick))
|
||||||
|
|
||||||
return state, events
|
return state, events
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user