diff --git a/strategies.py b/strategies.py index eb6629f..930a9ab 100644 --- a/strategies.py +++ b/strategies.py @@ -141,9 +141,15 @@ class FormulaInvesting(Investing): def notify_timer(self, timer, when, *args): super().notify_timer(timer, when, *args) self.formula() + self.prev_value = self.broker.get_value() class VA(FormulaInvesting): + """ + When market is down, buy + When up, sell. Shitty strategy: https://en.wikipedia.org/wiki/Value_averaging + """ + def formula(self): target_value = ( min( @@ -156,25 +162,65 @@ class VA(FormulaInvesting): # self.broker.set_cash(self.broker.get_cash() * self.monthly_params["t_rate"]) +class QVA(VA): + """ + Same but quarterly + """ + + def formula(self): + if not self.months % 3: + super().formula() + + class DCA(FormulaInvesting): + """ + Buy everything monthly + """ + def formula(self): target_value = self.broker.get_value() - reserve self.order_target_value(target=target_value) -class QVA(VA): +class QDCA(DCA): + """ + Buy everything quarterly + """ + def formula(self): if not self.months % 3: super().formula() -class QDCA(DCA): - def formula(self): - if not self.months % 3: - super().formula() +class EDCA(Investing): + """ + When market is down, BUY THE DIP + When up, leave some cash + """ + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.prev_value = 0 + + def notify_timer(self, timer, when, *args): + self.months += 1 + + if self.prev_value >= self.broker.get_value(): + self.broker.add_cash(1.1 * self.monthly_cash) + else: + self.broker.add_cash(0.9 * self.monthly_cash) + + target_value = self.broker.get_value() + self.order_target_value(target=target_value - reserve) + + self.prev_value = self.broker.get_value() class SmaCross(Investing): + """ + Buy when fast moving average crosses slow upwards + """ + params = dict( pfast=8, # period for the fast moving average pslow=17, # period for the slow moving average @@ -191,13 +237,3 @@ class SmaCross(Investing): self.order_target_value( target=self.broker.get_value() - reserve ) # enter long - - -class SmaVA(SmaCross): - def next(self): - if not self.position: # not in the market - if self.crossover > 0: # if fast crosses slow to the upside - self.order_target_value(target=self.broker.get_cash()) # enter long - - elif self.crossover < 0: # in the market & cross to the downside - self.order_target_value(target=self.broker.get_value() / 2) # close half diff --git a/year_intervals.py b/year_intervals.py index c646ab8..75cfa76 100644 --- a/year_intervals.py +++ b/year_intervals.py @@ -6,13 +6,13 @@ import pandas as pd if __name__ == "__main__": stockList = ["^GSPC"] - monthly_params = dict(sum=1000, coef=1, t_rate=1 + 0.02 / 12) + monthly_params = dict(sum=100000, coef=1, t_rate=1 + 0.02 / 12) # startDate = datetime.datetime.fromisoformat("2000-01-01") # endDate = datetime.datetime.fromisoformat("2022-01-01") print(stockList[0]) stockData = lib.get_data(stockList[0]) start_date = stockData.index[0] - year_step = 5 + year_step = 1 label_string = "Investing to {} monthly over {} years, increasing {:.2f}%, starting from ${}".format( stockList[0], year_step, @@ -21,15 +21,20 @@ if __name__ == "__main__": ) print(label_string) plot_param = "annual%" - strategies = ( - st.DCA, + + _strategies = ( st.QDCA, + st.EDCA, st.SmaCross, ) + strategies = (st.DCA,) + _strategies df_comp = pd.DataFrame(index=list(st.__name__ for st in strategies)) df_vwr = pd.DataFrame(index=list(st.__name__ for st in strategies)) - for start_year in range(start_date.year, datetime.datetime.today().year, year_step): + df_rel_to_dca = pd.DataFrame(index=list(st.__name__ for st in _strategies)) + for start_year in range( + start_date.year, datetime.datetime.today().year - year_step + 1, 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: @@ -50,12 +55,19 @@ if __name__ == "__main__": ] ) print(newdf.to_string()) + df_rel_to_dca[start_year] = list( + newdf.loc[s.__name__][plot_param] - newdf.loc[st.DCA.__name__][plot_param] + for s in _strategies + ) df_comp[start_year] = newdf[plot_param].values # print(df[["annual%", "froi%", "cost", "total_value", "max_dd%", "max_md"]]) # print(newdf["annual%"]) - print(df_comp.to_string()) + print(df_rel_to_dca.to_string()) df_comp.T.plot() + for index, s in df_rel_to_dca.iterrows(): + print("{}: avg {:.3f} dev {:.3f}".format(index, s.mean(), s.std())) + df_rel_to_dca.T.hist(bins=20) plt.grid() plt.title(label_string) plt.ylabel(plot_param)