You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
54 lines
1.7 KiB
54 lines
1.7 KiB
from typing import Dict, Callable, List
|
|
|
|
from ..interfaces import PTF, PTFState
|
|
from ..orders import Long, Short
|
|
from ..errors import OrderFails
|
|
|
|
|
|
class InMemoryPortfolio(PTF):
|
|
"""Just store the value in memory."""
|
|
|
|
_balance: float
|
|
_stocks: Dict[str, float]
|
|
|
|
def __init__(
|
|
self,
|
|
change_rate_getter: Callable[[], Dict[str, float]],
|
|
base_balance: float = 0,
|
|
**kwargs
|
|
):
|
|
"""Init the class with a pointer to the bot to retrieve the change rate."""
|
|
super().__init__(**kwargs)
|
|
self._balance = base_balance
|
|
self._stocks = {}
|
|
self.change_rate_getter = change_rate_getter
|
|
|
|
@property
|
|
def state(self):
|
|
return PTFState(self._balance, self._stocks.copy())
|
|
|
|
@property
|
|
def change_rate(self) -> Dict[str, float]:
|
|
return self.change_rate_getter()
|
|
|
|
def execute_short(self, order: Short) -> None:
|
|
"""Sell actions."""
|
|
if self._stocks[order.stock] < order.amount:
|
|
raise OrderFails("Not enough stock.")
|
|
if self.change_rate.get(order.stock, 0) < order.price:
|
|
raise OrderFails("You shell it too high.")
|
|
|
|
self._balance += order.price * order.amount
|
|
self._stocks[order.stock] -= order.amount
|
|
|
|
def execute_long(self, order: Long) -> None:
|
|
"""Buy actions."""
|
|
if self.balance < order.amount * order.price:
|
|
raise OrderFails("Not enough money.")
|
|
if self.change_rate.get(order.stock, 0) > order.price:
|
|
raise OrderFails("You buy it too low.")
|
|
|
|
self._balance -= order.price * order.amount
|
|
self._stocks[order.stock] = order.amount + self._stocks.get(order.stock, 0)
|
|
|
|
executors = {Short: execute_short, Long: execute_long}
|
|
|