From 9efa0aee5899584994ef175d8a23c19ec4f5b766 Mon Sep 17 00:00:00 2001 From: Dmitry Maylarov Date: Sun, 30 Jan 2022 20:15:58 +0300 Subject: [PATCH] table --- dcavslsi.py => compare.py | 100 +++++++++++++++++++++++--------------- 1 file changed, 60 insertions(+), 40 deletions(-) rename dcavslsi.py => compare.py (72%) diff --git a/dcavslsi.py b/compare.py similarity index 72% rename from dcavslsi.py rename to compare.py index a6a7d2a..000a2c4 100644 --- a/dcavslsi.py +++ b/compare.py @@ -10,7 +10,8 @@ stockList = ["VOO"] total_days_in_market = 365 * 10 month_sum = 500 # usd reserve = 5 # usd for comms etc -startDate = datetime.datetime.fromisoformat("2018-01-01") +startDate = datetime.datetime.fromisoformat("2000-01-01") +endDate = datetime.datetime.fromisoformat("2022-01-30") # import data @@ -19,12 +20,11 @@ def get_data(stocks, start, end): return stockData -endDate = datetime.datetime.now() +# 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] -print(actualStart) data = bt.feeds.PandasData(dataname=stockData) @@ -59,14 +59,11 @@ class PercentageCommisionScheme(bt.CommInfoBase): ("commtype", bt.CommInfoBase.COMM_PERC), ) - def _getcommission(self, size, price, pseudoexec): - return self.p.commission - class FormulaInvesting(bt.Strategy): def __init__(self): self.order = None - self.totalcost = 0 + self.cost = 0 # no comms self.comms = 0 self.units = 0 self.times = 0 @@ -107,7 +104,7 @@ class FormulaInvesting(bt.Strategy): ) self.units += order.executed.size - self.totalcost += order.executed.value + order.executed.comm + self.cost += order.executed.value self.comms += order.executed.comm elif order.issell(): @@ -121,10 +118,8 @@ class FormulaInvesting(bt.Strategy): ) ) self.units -= order.executed.size - # self.totalcost += order.executed.value - self.totalcost += order.executed.comm - self.comms -= order.executed.value + self.comms += order.executed.comm self.times += 1 elif order.status in [order.Canceled, order.Margin, order.Rejected]: @@ -138,24 +133,17 @@ class FormulaInvesting(bt.Strategy): def calc_params(self): # calculate actual returns - self.roi = (self.broker.get_value() / self.cash_start) - 1 self.froi = self.broker.get_fundvalue() - self.val_start value = self.datas[0].close * self.units + self.broker.get_cash() - print("Time in Market: {:.1f} years".format((endDate - actualStart).days / 365)) - print("#Times: {:.0f}".format(self.times)) - print("#Units: {:.0f}".format(self.units)) - print("Value: ${:,.2f}".format(value)) - print("Commissions: ${:.2f}".format(self.froi)) - print("Cost: ${:,.2f}".format(self.totalcost)) - print("Gross Return: ${:,.2f}".format(value - self.totalcost)) - print("Gross %: {:.2f}%".format((value / self.totalcost - 1) * 100)) - print("ROI: {:.2f}%".format(100.0 * self.roi)) - print("Fund Value: {:.2f}%".format(self.froi)) - print( - "Annualised: {:.2f}%".format( - 100 - * ((1 + self.froi / 100) ** (365 / (endDate - actualStart).days) - 1) - ) + return ( + # Annual + 100 * ((1 + self.froi / 100) ** (365 / (endDate - actualStart).days) - 1), + self.froi, + self.cost, + value, + self.times, + self.units, + self.comms, ) def notify_timer(self, timer, when, *args): @@ -188,11 +176,13 @@ class QDCA(DCA): super().formula() -def run(strategy, data): - cerebro = bt.Cerebro(stdstats=False) - - cerebro.addobserver(bt.observers.Broker) - cerebro.addobserver(bt.observers.BuySell) +def run(strategy, data, fund_mode=False): + if fund_mode: + cerebro = bt.Cerebro() + else: + cerebro = bt.Cerebro(stdstats=False) + cerebro.addobserver(bt.observers.Broker) + cerebro.addobserver(bt.observers.BuySell) cerebro.adddata(data) cerebro.addstrategy(strategy) @@ -205,20 +195,50 @@ def run(strategy, data): comminfo = PercentageCommisionScheme() cerebro.broker.addcommissioninfo(comminfo) + if fund_mode: + cerebro.broker.set_fundmode(True) + cerebro.broker.set_cash(month_sum) - # cerebro.addobserver(bt.observers.FundValue) - # cerebro.addobserver(bt.observers.FundShares) cerebro.addanalyzer(bt.analyzers.DrawDown, _name="drawdown") cerebro.addanalyzer(bt.analyzers.VWR, _name="returns") + cerebro.addanalyzer( + bt.analyzers.TimeReturn, timeframe=bt.TimeFrame.NoTimeFrame, _name="tr" + ) thestrats = cerebro.run() thestrat = thestrats[0] - dd = thestrat.analyzers.drawdown - print(dd.get_analysis().max) - ret = thestrat.analyzers.returns - print(ret.get_analysis()) cerebro.plot(iplot=False, style="candlestick") + return thestrat if __name__ == "__main__": - for strategy in (DCA, QDCA, VA, QVA): - run(strategy, data) + df = pd.DataFrame( + columns=[ + "annual%", + "froi", + "cost", + "total_value", + "times", + "units", + "comms", + "max_dd_len", + "max_dd", + "max_md", + "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)