class PnlAnalyzer(Analyzer): Pnl = "Pnl" def __init__(self, portfolio, state): self.portfolio = portfolio self.state = state self.series = DataSeries(time_series=self.state.pnl.series) def update(self, timestamp: int, total_equity: float): performance_series = self.portfolio.performance.series if self.series.size() >= 2: self.state.pnl.last_pnl = performance_series.get_by_idx(-1, PerformanceAnalyzer.TotalEquity) - \ performance_series.get_by_idx(-2, PerformanceAnalyzer.TotalEquity) self.series.add(timestamp=timestamp, data={self.Pnl: self.state.pnl.last_pnl}) else: self.state.pnl.last_pnl = 0 self.series.add(timestamp=timestamp, data={self.Pnl: self.state.pnl.last_pnl}) def get_result(self): return {self.Pnl: self.state.pnl.last_pnl} def get_series(self, keys=None): keys = keys if keys else self.Pnl return {self.Pnl: self.series.get_series(self.Pnl)} def last_pnl(self) -> float: return self.state.pnl.last_pnl
def __create_plot(self): series = DataSeries(time_series=TimeSeries()) t = 20170101 for idx, value in enumerate(self.values): ts = datestr_to_unixtimemillis(t) series.add(timestamp=ts, data={"value": value}) t = t + 1 values = series.get_series(["value"]) plot = TimeSeriesPlot(values) return plot
class PerformanceAnalyzer(Analyzer): Performance = "Performance" StockValue = "stock_value" Cash = "cash" TotalEquity = "total_equity" def __init__(self, portfolio, state): self.portfolio = portfolio self.state = state self.series = DataSeries(time_series=self.state.performance.series) def update(self, timestamp: int, total_equity: float): self.state.performance.total_equity = total_equity self.series.add(timestamp=timestamp, data={ self.StockValue: self.state.stock_value, self.Cash: self.state.cash, self.TotalEquity: total_equity }) def get_result(self): return { self.StockValue: self.state.stock_value, self.Cash: self.state.cash, self.TotalEquity: self.state.performance.total_equity } def get_series(self, keys=None): keys = keys if keys else [self.StockValue, self.Cash, self.TotalEquity] return self.series.get_series(keys) def now(self, key): return self.series.now(key) def total_equity(self) -> float: return self.state.performance.total_equity
class DrawDownAnalyzer(Analyzer): DrawDown = "DrawDown" DrawDownPct = "DrawDown%" HighEquity = "HighEquity" LowEquity = "LowEquity" CurrentRunUp = "CurrentRunUp" CurrentDrawDown = "CurrentDrawDown" def __init__(self, portfolio, state): self.portfolio = portfolio self.state = state self.series = DataSeries(time_series=self.state.drawdown.series) def update(self, timestamp: int, total_equity: float): if self.portfolio.performance.series.size() == 1: self.state.drawdown.low_equity = total_equity self.state.drawdown.high_equity = total_equity else: if total_equity > self.state.drawdown.high_equity: self.state.drawdown.high_equity = total_equity self.state.drawdown.low_equity = total_equity self.state.drawdown.current_drawdown = 0 elif total_equity < self.state.drawdown.low_equity: self.state.drawdown.low_equity = total_equity self.state.drawdown.current_run_up = 0 elif total_equity > self.state.drawdown.low_equity and total_equity < self.state.drawdown.high_equity: self.state.drawdown.current_drawdown = 1 - total_equity / self.state.drawdown.high_equity self.state.drawdown.current_run_up = total_equity / self.state.drawdown.low_equity - 1 if self.portfolio.performance.series.size() >= 2: self.state.drawdown.last_drawdown = total_equity - self.state.drawdown.high_equity if self.state.drawdown.high_equity != 0: self.state.drawdown.last_drawdown_pct = abs( self.state.drawdown.last_drawdown / self.state.drawdown.high_equity) self.series.add(timestamp=timestamp, data={ self.DrawDown: self.state.drawdown.last_drawdown, self.DrawDownPct: self.state.drawdown.last_drawdown_pct }) def get_result(self): return { self.DrawDown: self.state.drawdown.last_drawdown, self.DrawDownPct: self.state.drawdown.last_drawdown_pct, self.HighEquity: self.state.drawdown.high_equity, self.LowEquity: self.state.drawdown.low_equity, self.CurrentRunUp: self.state.drawdown.current_run_up, self.CurrentDrawDown: self.state.drawdown.current_drawdown } def get_series(self, keys=None): keys = keys if keys else [self.DrawDown, self.DrawDownPct] return self.series.get_series(keys) def last_drawdown(self) -> float: return self.state.drawdown.last_drawdown def last_drawdown_pct(self) -> float: return self.state.drawdown.last_drawdown_pct def high_equity(self) -> float: return self.state.drawdown.high_equity def low_equity(self) -> float: return self.state.drawdown.low_equity def current_run_up(self) -> float: return self.state.drawdown.current_run_up def current_drawdown(self) -> float: return self.state.drawdown.current_drawdown