From fb7fda1e27905d5f79b210ee0ca8a9efb1b26b6c Mon Sep 17 00:00:00 2001 From: Dmitry Maylarov Date: Sun, 30 Jan 2022 21:51:34 +0300 Subject: [PATCH] nice table over years --- compare.py | 118 +++++++++++++++++++++++------------------------------ 1 file changed, 52 insertions(+), 66 deletions(-) diff --git a/compare.py b/compare.py index 000a2c4..7d03269 100644 --- a/compare.py +++ b/compare.py @@ -6,27 +6,11 @@ import matplotlib.pyplot as plt from pandas_datareader import data as pdr import backtrader as bt -stockList = ["VOO"] -total_days_in_market = 365 * 10 +stockList = ["SWPPX"] month_sum = 500 # usd reserve = 5 # usd for comms etc -startDate = datetime.datetime.fromisoformat("2000-01-01") -endDate = datetime.datetime.fromisoformat("2022-01-30") - - -# import data -def get_data(stocks, start, end): - stockData = pdr.get_data_yahoo(stocks, start, end) - return stockData - - -# endDate = datetime.datetime.now() -# startDate = endDate - datetime.timedelta(days=total_days_in_market) -stockData = get_data(stockList[0], startDate, endDate) - -actualStart: datetime.datetime = stockData.index[0] - -data = bt.feeds.PandasData(dataname=stockData) +# startDate = datetime.datetime.fromisoformat("2000-01-01") +# endDate = datetime.datetime.fromisoformat("2022-01-01") class LSI(bt.Strategy): @@ -53,12 +37,15 @@ class LSI(bt.Strategy): class PercentageCommisionScheme(bt.CommInfoBase): - paras = ( + params = ( ("commission", 0.004), ("stocklike", True), ("commtype", bt.CommInfoBase.COMM_PERC), ) + def _getcommission(self, size, price, pseudoexec): + return size * price * self.p.commission + 4 # 290rub/month + class FormulaInvesting(bt.Strategy): def __init__(self): @@ -71,10 +58,10 @@ class FormulaInvesting(bt.Strategy): def log(self, txt, dt=None): dt = dt or self.datas[0].datetime.date(0) - print("%s, %s" % (dt.isoformat(), txt)) + # print("%s, %s" % (dt.isoformat(), txt)) def start(self): - # self.broker.set_fundmode(fundmode=True, fundstartval=100.0) + self.broker.set_fundmode(fundmode=True, fundstartval=100.0) self.cash_start = self.broker.get_cash() self.val_start = 100.0 @@ -93,32 +80,23 @@ class FormulaInvesting(bt.Strategy): if order.status in [order.Completed]: if order.isbuy(): - self.log( - "BUY EXECUTED, Price %.2f, Cost %.2f, Comm %.2f, Size %.0f" - % ( - order.executed.price, - order.executed.value, - order.executed.comm, - order.executed.size, - ) - ) - self.units += order.executed.size self.cost += order.executed.value - self.comms += order.executed.comm elif order.issell(): - self.log( - "SELL EXECUTED, Price %.2f, Cost %.2f, Comm %.2f, Size %.0f" - % ( - order.executed.price, - order.executed.value, - order.executed.comm, - order.executed.size, - ) - ) self.units -= order.executed.size + self.log( + "%s Price %.2f, Units %.0f, Value %.2f, Comm %.2f, " + % ( + "BUY" if order.isbuy else "SELL", + order.executed.price, + order.executed.size, + order.executed.value, + order.executed.comm, + ) + ) + self.comms += order.executed.comm self.times += 1 @@ -128,19 +106,15 @@ class FormulaInvesting(bt.Strategy): self.order = None - def stop(self): - self.calc_params() - def calc_params(self): # calculate actual returns self.froi = self.broker.get_fundvalue() - self.val_start - value = self.datas[0].close * self.units + self.broker.get_cash() return ( # Annual 100 * ((1 + self.froi / 100) ** (365 / (endDate - actualStart).days) - 1), self.froi, self.cost, - value, + self.broker.get_value() + self.broker.get_cash(), self.times, self.units, self.comms, @@ -179,6 +153,7 @@ class QDCA(DCA): def run(strategy, data, fund_mode=False): if fund_mode: cerebro = bt.Cerebro() + cerebro.addobserver(bt.observers.FundShares) else: cerebro = bt.Cerebro(stdstats=False) cerebro.addobserver(bt.observers.Broker) @@ -186,8 +161,6 @@ def run(strategy, data, fund_mode=False): cerebro.adddata(data) cerebro.addstrategy(strategy) - print("-" * 50) - print(strategy.__name__) # Broker Information broker_args = dict(coc=True) @@ -206,7 +179,7 @@ def run(strategy, data, fund_mode=False): ) thestrats = cerebro.run() thestrat = thestrats[0] - cerebro.plot(iplot=False, style="candlestick") + # cerebro.plot(iplot=False, style="candlestick") return thestrat @@ -226,19 +199,32 @@ if __name__ == "__main__": "twr", ] ) - for i, strategy in enumerate((DCA, QDCA, VA, QVA)): - therun = run(strategy, data) - dd = therun.analyzers.drawdown - ret = therun.analyzers.returns - # tr = thestrat.analyzers.tr - # print(next(reversed(tr.get_analysis()))) - # print(tr.get_analysis()) - df.loc[strategy.__name__] = therun.calc_params() + ( - dd.get_analysis().max.len, - dd.get_analysis().max.drawdown, - dd.get_analysis().max.moneydown, - ret.get_analysis()["vwr"], - ) - print("Starting from:", actualStart) - print("Time in Market: {:.1f} years".format((endDate - actualStart).days / 365)) - print(df) + # import data + def get_data(stocks, start, end): + stockData = pdr.get_data_yahoo(stocks, start, end) + return stockData + + for period_years in (1, 2, 5, 10, 15, 20, 25): + endDate = datetime.datetime.now() + startDate = endDate - datetime.timedelta(days=period_years * 365) + stockData = get_data(stockList[0], startDate, endDate) + actualStart: datetime.datetime = stockData.index[0] + data = bt.feeds.PandasData(dataname=stockData) + + for i, strategy in enumerate((DCA, QDCA)): # , VA, QVA)): + therun = run(strategy, data) + dd = therun.analyzers.drawdown + ret = therun.analyzers.returns + # tr = thestrat.analyzers.tr + # print(next(reversed(tr.get_analysis()))) + # print(tr.get_analysis()) + df.loc[strategy.__name__] = therun.calc_params() + ( + dd.get_analysis().max.len, + dd.get_analysis().max.drawdown, + dd.get_analysis().max.moneydown, + ret.get_analysis()["vwr"], + ) + print("Starting from:", actualStart) + print("Time in Market: {:.1f} years".format((endDate - actualStart).days / 365)) + print(df[["annual%", "froi", "cost", "total_value"]]) + # print(df)