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.

113 lines
3.6 KiB

import datetime
import math
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import backtrader as bt
import strategies as st
# import data
def get_data(stocks, start, end):
from pandas_datareader.yahoo.headers import DEFAULT_HEADERS
from pandas_datareader import data as pdr
import requests_cache
expire_after = datetime.timedelta(days=1)
session = requests_cache.CachedSession(
cache_name="cache", backend="sqlite", expire_after=expire_after
)
session.headers = DEFAULT_HEADERS
start = datetime.datetime.fromisoformat("1900-01-01")
end = datetime.datetime.now()
stockData = pdr.get_data_yahoo(stocks, start, end, session=session)
return stockData
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)
cerebro.addobserver(bt.observers.BuySell)
cerebro.adddata(data)
cerebro.addstrategy(strategy)
# Broker Information
broker_args = dict(coc=True)
cerebro.broker = bt.brokers.BackBroker(**broker_args)
comminfo = st.PercentageCommisionScheme()
cerebro.broker.addcommissioninfo(comminfo)
if fund_mode:
cerebro.broker.set_fundmode(True)
cerebro.broker.set_cash(st.month_sum)
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]
# cerebro.plot(iplot=False, style="candlestick")
return thestrat
if __name__ == "__main__":
df = pd.DataFrame(
columns=[
"froi",
"cost",
"total_value",
"times",
"units",
"comms",
"annual%",
"max_dd_len",
"max_dd",
"max_md",
"twr",
"tr",
]
)
stockList = ["^GSPC"]
# startDate = datetime.datetime.fromisoformat("2000-01-01")
# endDate = datetime.datetime.fromisoformat("2022-01-01")
print(stockList[0])
for period_years in (20, 50):
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(
(st.SmaCross, st.DCA, st.QDCA, st.VA, st.QVA, st.SmaVA)
):
therun = run(strategy, data)
dd = therun.analyzers.drawdown
ret = therun.analyzers.returns
tr = therun.analyzers.tr
# print(next(reversed(tr.get_analysis())))
params = therun.calc_params()
annual = 100 * (
(1 + params[0] / 100) ** (365 / (endDate - actualStart).days) - 1
)
df.loc[strategy.__name__] = therun.calc_params() + (
annual,
dd.get_analysis().max.len,
dd.get_analysis().max.drawdown,
dd.get_analysis().max.moneydown,
ret.get_analysis()["vwr"],
list(tr.get_analysis().items())[0][1],
)
print("Starting from:", actualStart)
print("Time in Market: {:.1f} years".format((endDate - actualStart).days / 365))
# print(df[["annual%", "froi", "cost", "total_value", "max_dd", "max_md"]])
print(df)