some organizing

master
Dmitry Maylarov 4 years ago
parent 2f009d87dd
commit be0652581e

@ -1,9 +1,12 @@
import datetime
import lib
from matplotlib import pyplot as plt
import strategies as st
import pandas as pd
if __name__ == "__main__":
stockList = ["^GSPC"]
monthly_params = dict(sum=10000, coef=1.005, t_rate=1 + 0.02 / 12)
stockList = ["BRK-A"]
monthly_params = dict(sum=100000, coef=1.005, t_rate=1 + 0.02 / 12)
# startDate = datetime.datetime.fromisoformat("2000-01-01")
# endDate = datetime.datetime.fromisoformat("2022-01-01")
print(stockList[0])
@ -17,13 +20,35 @@ if __name__ == "__main__":
period_years = 5
stockData = lib.get_data(
stockList[0],
datetime.datetime.fromisoformat("1928-01-01"),
datetime.datetime.now(),
)
start_date = stockData.index[0]
year_step = 5
year_step = 3
print(
"Investing monthly, increasing {:.2f}%, starting from ${}".format(
(monthly_params["coef"] * 100) - 100,
monthly_params["sum"],
)
)
for start_year in range(start_date.year, datetime.datetime.today().year, year_step):
start_date = datetime.date(start_year, 1, 1)
end_date = datetime.date(start_year + year_step - 1, 12, 31)
if (today := datetime.date.today()) < end_date:
end_date = today
stockData = lib.get_data(stockList[0], start_date, end_date)
lib.simulate(stockData, monthly_params)
start, end = lib.get_data_borders(stockData)
print(
"{} to {}, {:.1f} years".format(
start,
end,
(end - start).days / 365,
)
)
newdf = pd.concat(
[
lib.test_strategy(stockData, strategy, monthly_params)
for strategy in (st.DCA, st.QDCA)
]
)
print(newdf.to_string())
# print(df[["annual%", "froi%", "cost", "total_value", "max_dd%", "max_md"]])
# print(newdf["annual%"])

@ -4,8 +4,26 @@ import backtrader as bt
import strategies as st
COLUMNS = [
"froi%",
"cost",
"total_value",
"#deals",
"#units",
"comms",
"monthly",
"annual%",
"max_dd_days",
"max_dd%",
"max_md",
"vwr",
]
# import data
def get_data(stocks, start, end):
def get_data(
stocks,
start=datetime.datetime.fromisoformat("1928-01-01"),
end=datetime.datetime.now(),
):
from pandas_datareader.yahoo.headers import DEFAULT_HEADERS
from pandas_datareader import data as pdr
import requests_cache
@ -24,6 +42,12 @@ def get_data(stocks, start, end):
return stockData.loc[start:end]
def get_data_borders(stockData):
actual_start: datetime.datetime = stockData.index[0]
actual_end: datetime.datetime = stockData.index[-1]
return actual_start, actual_end
def human_readable_size(size, decimal_places=3):
for unit in ["$", "K$", "M$", "G$", "T$", "P$"]:
if size < 1000.0 or unit == "P$":
@ -58,57 +82,29 @@ def prepare_simulation(strategy, params, data, fund_mode=False):
return cerebro
def simulate(stockData, monthly_params):
def test_strategy(stockData, strategy, monthly_params):
pd.options.display.float_format = "{:,.2f}".format
df = pd.DataFrame(
columns=[
"froi%",
"cost",
"total_value",
"#deals",
"#units",
"comms",
"monthly",
"annual%",
"max_dd_days",
"max_dd%",
"max_md",
"vwr",
]
)
actualStart: datetime.datetime = stockData.index[0]
actualEnd: datetime.datetime = stockData.index[-1]
df = pd.DataFrame(columns=COLUMNS)
actual_start, actual_end = get_data_borders(stockData)
data = bt.feeds.PandasData(dataname=stockData)
for i, strategy in enumerate((st.DCA, st.QDCA, st.VA, st.QVA)):
cerebro = prepare_simulation(strategy, monthly_params, data)
therun = cerebro.run()[0]
# cerebro.plot(iplot=False, style="candlestick")
dd = therun.analyzers.drawdown
ret = therun.analyzers.returns
params = therun.calc_params()
# omg IM so sorry for this, ironically this is here to get human readable size
for i in 1, 2, 5, 6:
params[i] = human_readable_size(params[i])
annual = 100 * (
(1 + params[0] / 100) ** (365 / (actualEnd - actualStart).days) - 1
)
df.loc[strategy.__name__] = params + [
annual,
dd.get_analysis().max.len,
dd.get_analysis().max.drawdown,
human_readable_size(dd.get_analysis().max.moneydown),
ret.get_analysis()["vwr"],
]
print(
"Investing monthly, increasing {:.2f}%, starting from ${}, from {} to {}, {:.1f} years".format(
(monthly_params["coef"] * 100) - 100,
monthly_params["sum"],
actualStart.date(),
actualEnd.date(),
(actualEnd - actualStart).days / 365,
)
cerebro = prepare_simulation(strategy, monthly_params, data)
therun = cerebro.run()[0]
# cerebro.plot(iplot=False, style="candlestick")
dd = therun.analyzers.drawdown
ret = therun.analyzers.returns
params = therun.calc_params()
# omg IM so sorry for this, ironically this is here to get human readable size
for i in 1, 2, 5, 6:
params[i] = human_readable_size(params[i])
annual = 100 * (
(1 + params[0] / 100) ** (365 / (actual_end - actual_start).days) - 1
)
# print(df[["annual%", "froi%", "cost", "total_value", "max_dd%", "max_md"]])
print(df.to_string())
df.loc[strategy.__name__] = params + [
annual,
dd.get_analysis().max.len,
dd.get_analysis().max.drawdown,
human_readable_size(dd.get_analysis().max.moneydown),
ret.get_analysis()["vwr"],
]
return df

Loading…
Cancel
Save