pybottrader.portfolios

Portfolio Managers

Portfolio managers, to implement buy/sell policies and deliver orders. Currently only a DummyPortfolio is implemented, one that when receives a buy signal buys everything that it can with its available cash, and sells all its assets when receives a sell signal. This portfolio can be used for back-testing.

 1"""
 2# Portfolio Managers
 3
 4Portfolio managers, to implement buy/sell policies and deliver orders.
 5Currently only a `DummyPortfolio` is implemented, one that when receives a `buy`
 6signal buys everything that it can with its available cash, and sells all its
 7assets when receives a `sell` signal. This portfolio can be used for
 8back-testing.
 9"""
10
11from .strategies import Position, StrategySignal
12from .indicators import roi
13
14
15class Portfolio:
16    """Base Portfolio Class"""
17
18    initial_cash: float
19    last_position: Position
20    last_exchange: str
21    last_price: float
22    last_ticker: str
23
24    def __init__(self, cash: float = 1000.0):
25        """Init method"""
26        self.initial_cash = cash
27        self.last_position = Position.STAY
28        self.last_price = 0.0
29        self.last_ticker = ""
30        self.last_exchange = ""
31
32    def process(self, signal: StrategySignal):
33        """Process signal"""
34        self.last_ticker = signal.ticker
35        self.last_price = signal.price
36        self.last_position = signal.position
37        self.last_exchange = signal.exchange
38
39    def valuation(self) -> float:
40        """Default valuation method"""
41        return self.initial_cash
42
43    def accumulated_return(self) -> float:
44        """Accumulated ROI"""
45        return roi(self.initial_cash, self.valuation())
46
47
48class DummyPortfolio(Portfolio):
49    """
50    Dummy portfolio is the most basic portfolio model.
51    It works with only one asset. When it receives the buy signal,
52    it uses all the available cash to buy the asset. When it receives
53    the sell signal, it sells all the shares of the asset.
54    """
55
56    cash: float
57    share_units: float
58    share_price: float
59
60    def __init__(self, cash: float = 1000.0):
61        super().__init__(cash)
62        self.cash = cash
63        self.share_units = 0.0
64        self.share_price = 0.0
65
66    def process(self, signal: StrategySignal):
67        super().process(signal)
68        if signal.position == Position.BUY:
69            if self.cash == 0.0:
70                return
71            self.share_units = self.cash / signal.price
72            self.share_price = signal.price
73            self.cash = 0.0
74        elif signal.position == Position.SELL:
75            if self.share_units == 0.0:
76                return
77            self.cash = self.share_units * signal.price
78            self.share_price = signal.price
79            self.share_units = 0.0
80
81    def valuation(self) -> float:
82        return self.cash if self.cash > 0.0 else (self.share_price * self.share_units)
class Portfolio:
16class Portfolio:
17    """Base Portfolio Class"""
18
19    initial_cash: float
20    last_position: Position
21    last_exchange: str
22    last_price: float
23    last_ticker: str
24
25    def __init__(self, cash: float = 1000.0):
26        """Init method"""
27        self.initial_cash = cash
28        self.last_position = Position.STAY
29        self.last_price = 0.0
30        self.last_ticker = ""
31        self.last_exchange = ""
32
33    def process(self, signal: StrategySignal):
34        """Process signal"""
35        self.last_ticker = signal.ticker
36        self.last_price = signal.price
37        self.last_position = signal.position
38        self.last_exchange = signal.exchange
39
40    def valuation(self) -> float:
41        """Default valuation method"""
42        return self.initial_cash
43
44    def accumulated_return(self) -> float:
45        """Accumulated ROI"""
46        return roi(self.initial_cash, self.valuation())

Base Portfolio Class

Portfolio(cash: float = 1000.0)
25    def __init__(self, cash: float = 1000.0):
26        """Init method"""
27        self.initial_cash = cash
28        self.last_position = Position.STAY
29        self.last_price = 0.0
30        self.last_ticker = ""
31        self.last_exchange = ""

Init method

initial_cash: float
last_exchange: str
last_price: float
last_ticker: str
def process(self, signal: pybottrader.strategies.StrategySignal):
33    def process(self, signal: StrategySignal):
34        """Process signal"""
35        self.last_ticker = signal.ticker
36        self.last_price = signal.price
37        self.last_position = signal.position
38        self.last_exchange = signal.exchange

Process signal

def valuation(self) -> float:
40    def valuation(self) -> float:
41        """Default valuation method"""
42        return self.initial_cash

Default valuation method

def accumulated_return(self) -> float:
44    def accumulated_return(self) -> float:
45        """Accumulated ROI"""
46        return roi(self.initial_cash, self.valuation())

Accumulated ROI

class DummyPortfolio(Portfolio):
49class DummyPortfolio(Portfolio):
50    """
51    Dummy portfolio is the most basic portfolio model.
52    It works with only one asset. When it receives the buy signal,
53    it uses all the available cash to buy the asset. When it receives
54    the sell signal, it sells all the shares of the asset.
55    """
56
57    cash: float
58    share_units: float
59    share_price: float
60
61    def __init__(self, cash: float = 1000.0):
62        super().__init__(cash)
63        self.cash = cash
64        self.share_units = 0.0
65        self.share_price = 0.0
66
67    def process(self, signal: StrategySignal):
68        super().process(signal)
69        if signal.position == Position.BUY:
70            if self.cash == 0.0:
71                return
72            self.share_units = self.cash / signal.price
73            self.share_price = signal.price
74            self.cash = 0.0
75        elif signal.position == Position.SELL:
76            if self.share_units == 0.0:
77                return
78            self.cash = self.share_units * signal.price
79            self.share_price = signal.price
80            self.share_units = 0.0
81
82    def valuation(self) -> float:
83        return self.cash if self.cash > 0.0 else (self.share_price * self.share_units)

Dummy portfolio is the most basic portfolio model. It works with only one asset. When it receives the buy signal, it uses all the available cash to buy the asset. When it receives the sell signal, it sells all the shares of the asset.

DummyPortfolio(cash: float = 1000.0)
61    def __init__(self, cash: float = 1000.0):
62        super().__init__(cash)
63        self.cash = cash
64        self.share_units = 0.0
65        self.share_price = 0.0

Init method

cash: float
share_units: float
share_price: float
def process(self, signal: pybottrader.strategies.StrategySignal):
67    def process(self, signal: StrategySignal):
68        super().process(signal)
69        if signal.position == Position.BUY:
70            if self.cash == 0.0:
71                return
72            self.share_units = self.cash / signal.price
73            self.share_price = signal.price
74            self.cash = 0.0
75        elif signal.position == Position.SELL:
76            if self.share_units == 0.0:
77                return
78            self.cash = self.share_units * signal.price
79            self.share_price = signal.price
80            self.share_units = 0.0

Process signal

def valuation(self) -> float:
82    def valuation(self) -> float:
83        return self.cash if self.cash > 0.0 else (self.share_price * self.share_units)

Default valuation method