1
0
Fork 0

Finish manual strategy for project 8

I struggled with the manual strategy, mostly because I tried to read
good triggers from the price action charts. Finally, I had the ingenious
(hmm) idea to scatter plot the 1, 3, and 5 day percentage returns over
different indicators. I can also use this information to train my Q
learner.
master
Felix Martin 2020-11-03 19:05:43 -05:00
parent 43e297c075
commit 0519ae9336
3 changed files with 108 additions and 46 deletions

View File

@ -58,19 +58,32 @@ class ManualStrategy:
orders['Shares'] = orders['Shares'].rolling(2).apply(strat) orders['Shares'] = orders['Shares'].rolling(2).apply(strat)
def three_indicator_strat(self, macd, rsi, price_sma, orders): def three_indicator_strat(self, macd, rsi, price_sma, orders):
# XXX: continue here
def strat(row): def strat(row):
m = macd.loc[row.index] shares = 0
print(m) _, _, macd_diff = macd.loc[row.name]
# mac, signal = m.iloc[0] cur_rsi = rsi.loc[row.name][0]
# print(mac, signal) cur_price_sma = price_sma.loc[row.name][0]
return 0 if self.holding == -1000 and cur_price_sma < 0.9:
shares = 2000
elif self.holding == 0 and cur_price_sma < 0.9:
shares = 1000
elif self.holding == -1000 and cur_rsi > 80:
shares = 2000
elif self.holding == 0 and cur_rsi > 80:
shares = 1000
elif self.holding == -1000 and macd_diff < -0.5:
shares = 2000
elif self.holding == 0 and macd_diff < -0.5:
shares = 1000
elif self.holding == 1000 and cur_price_sma > 1.1:
shares = -2000
elif self.holding == 0 and cur_price_sma > 1.1:
shares = -1000
self.holding += shares
return shares
orders['Shares'] = orders.apply(strat, axis=1) orders['Shares'] = orders.apply(strat, axis=1)
raise Exception()
# this method should use the existing policy and test it against new data
def testPolicy(self, symbol="IBM", def testPolicy(self, symbol="IBM",
sd=dt.datetime(2009, 1, 1), sd=dt.datetime(2009, 1, 1),
ed=dt.datetime(2010, 1, 1), ed=dt.datetime(2010, 1, 1),
@ -87,10 +100,9 @@ class ManualStrategy:
macd = indicators.macd(df, symbol) macd = indicators.macd(df, symbol)
rsi = indicators.rsi(df, symbol) rsi = indicators.rsi(df, symbol)
price_sma = indicators.price_sma(df, symbol, [21]) price_sma = indicators.price_sma(df, symbol, [8])
# self.macd_strat(macd, orders) # self.macd_strat(macd, orders)
self.three_indicator_strat(macd, rsi, price_sma, orders) self.three_indicator_strat(macd, rsi, price_sma, orders)
# heers = orders[orders["Shares"] != 0]
return orders return orders

View File

@ -1,22 +1,76 @@
import pandas as pd import pandas as pd
import datetime as dt import datetime as dt
import marketsim.marketsim as marketsim import sys
import indicators
import util import util
import indicators
import marketsim.marketsim as marketsim
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
from matplotlib.widgets import MultiCursor from matplotlib.widgets import MultiCursor
from BenchmarkStrategy import BenchmarkStrategy from BenchmarkStrategy import BenchmarkStrategy
from ManualStrategy import ManualStrategy from ManualStrategy import ManualStrategy
def plot_indicators(symbol, df):
fig, ax = plt.subplots(4, sharex=True)
price_sma = indicators.price_sma(df, symbol, [8])
bb = indicators.bollinger_band(df, symbol)
sma = indicators.sma(df, symbol, [8])
rsi = indicators.rsi(df, symbol)
macd = indicators.macd(df, symbol).copy()
df[[symbol]].plot(ax=ax[0])
bb.plot(ax=ax[0])
price_sma.plot(ax=ax[1])
macd.plot(ax=ax[2])
rsi.plot(ax=ax[3])
for a in ax.flat:
a.grid()
plt.show()
sys.exit(0)
def visualize_correlations(symbol, df):
indicators.price_sma(df, symbol, [8, 21])
indicators.price_delta(df, symbol, 5)
indicators.price_delta(df, symbol, 3)
indicators.price_delta(df, symbol, 1)
indicators.macd(df, symbol)
indicators.rsi(df, symbol)
# df = df[df['rsi'] > 80]
fig, ax = plt.subplots(3, 2) # sharex=True)
df.plot.scatter(x="price_sma_8", y="pct_5", ax=ax[0, 0])
df.plot.scatter(x="price_sma_8", y="pct_3", ax=ax[1, 0])
df.plot.scatter(x="price_sma_8", y="pct_1", ax=ax[2, 0])
# df.plot.scatter(x="rsi", y="pct_5", ax=ax[0, 1])
# df.plot.scatter(x="rsi", y="pct_3", ax=ax[1, 1])
# df.plot.scatter(x="rsi", y="pct_1", ax=ax[2, 1])
df.plot.scatter(x="macd_diff", y="pct_5", ax=ax[0, 1])
df.plot.scatter(x="macd_diff", y="pct_3", ax=ax[1, 1])
df.plot.scatter(x="macd_diff", y="pct_1", ax=ax[2, 1])
for a in ax.flat:
a.grid()
plt.show()
sys.exit(0)
def experiment1(): def experiment1():
symbol = "JPM" symbol = "JPM"
start_value = 10000 start_value = 10000
sd = dt.datetime(2008, 1, 1) sd = dt.datetime(2008, 1, 1) # in-sample
ed = dt.datetime(2009, 12, 31) ed = dt.datetime(2009, 12, 31) # in-sample
# sd = dt.datetime(2010, 1, 1) # out-sample
# ed = dt.datetime(2011, 12, 31) # out-sample
df = util.get_data([symbol], pd.date_range(sd, ed)) df = util.get_data([symbol], pd.date_range(sd, ed))
df.drop(columns=["SPY"], inplace=True) df.drop(columns=["SPY"], inplace=True)
# visualize_correlations(symbol, df)
# plot_indicators(symbol, df)
bs = BenchmarkStrategy() bs = BenchmarkStrategy()
orders = bs.testPolicy(symbol, sd, ed, start_value) orders = bs.testPolicy(symbol, sd, ed, start_value)
df["Benchmark"] = marketsim.compute_portvals(orders, start_value) df["Benchmark"] = marketsim.compute_portvals(orders, start_value)
@ -26,21 +80,12 @@ def experiment1():
orders = ms.testPolicy(symbol, sd, ed, start_value) orders = ms.testPolicy(symbol, sd, ed, start_value)
df["Manual"] = marketsim.compute_portvals(orders, start_value) df["Manual"] = marketsim.compute_portvals(orders, start_value)
df["Orders Manual"] = orders["Shares"] df["Orders Manual"] = orders["Shares"]
df["Holding Manual"] = orders["Shares"].cumsum()
price_sma = indicators.price_sma(df, symbol, [21]) fig, ax = plt.subplots(3, sharex=True)
bb = indicators.bollinger_band(df, symbol)
sma = indicators.sma(df, symbol, [9, 21])
rsi = indicators.rsi(df, symbol)
macd = indicators.macd(df, symbol).copy()
fig, ax = plt.subplots(4, sharex=True)
df[[symbol]].plot(ax=ax[0]) df[[symbol]].plot(ax=ax[0])
# bb.plot(ax=ax[0]) df[["Benchmark", "Manual"]].plot(ax=ax[1])
price_sma.plot(ax=ax[1]) df[["Orders Benchmark", "Orders Manual"]].plot(ax=ax[2])
macd.plot(ax=ax[2])
rsi.plot(ax=ax[3])
# df[["Benchmark", "Manual"]].plot(ax=ax[1])
# df[["Orders Benchmark", "Orders Manual"]].plot(ax=ax[2])
for a in ax: for a in ax:
a.grid() a.grid()
@ -48,11 +93,7 @@ def experiment1():
plt.show() plt.show()
# plt.savefig('figure_1.png') # plt.savefig('figure_1.png')
# You may use data from other symbols (such as SPY) to inform both your
# Manual Learner and Strategy Learner. The in-sample/development period is
# January 1, 2008 to December 31 2009. The out-of-sample/testing period is
# January 1, 2010 to December 31 2011.
if __name__ == "__main__": if __name__ == "__main__":
experiment1() experiment1()

View File

@ -17,9 +17,7 @@ def bollinger_band(df, symbol, period=20, m=2):
std = df[symbol].rolling(period).std() std = df[symbol].rolling(period).std()
boll_up = boll_sma + m * std boll_up = boll_sma + m * std
boll_lo = boll_sma - m * std boll_lo = boll_sma - m * std
key_sma = f"{symbol}-Boll({period})-sma" key_sma, key_up, key_lo = "boll_sma", "boll_up", "boll_lo"
key_up = f"{symbol}-Boll({period})-up"
key_lo = f"{symbol}-Boll({period})-lo"
df[key_sma] = boll_sma df[key_sma] = boll_sma
df[key_up] = boll_up df[key_up] = boll_up
df[key_lo] = boll_lo df[key_lo] = boll_lo
@ -32,7 +30,7 @@ def sma(df, symbol, period):
period = [period] period = [period]
keys = [] keys = []
for p in period: for p in period:
key = f"{symbol}-sma({p})" key = f"sma_{p}"
df[key] = df[symbol].rolling(p).mean() df[key] = df[symbol].rolling(p).mean()
keys.append(key) keys.append(key)
return df[keys] return df[keys]
@ -44,8 +42,8 @@ def ema(df, symbol, period):
period = [period] period = [period]
keys = [] keys = []
for p in period: for p in period:
key = f"{symbol}-ema({p})" key = f"ema_{p}"
df[key] = df[symbol].ewm(span=period).mean() df[key] = df[symbol].ewm(span=p).mean()
keys.append(key) keys.append(key)
return df[keys] return df[keys]
@ -56,7 +54,7 @@ def price_sma(df, symbol, period):
period = [period] period = [period]
keys = [] keys = []
for p in period: for p in period:
key = f"{symbol}-price/sma({p})" key = f"price_sma_{p}"
sma = df[symbol].rolling(p).mean() sma = df[symbol].rolling(p).mean()
df[key] = df[symbol] / sma df[key] = df[symbol] / sma
keys.append(key) keys.append(key)
@ -84,16 +82,28 @@ def rsi(df, symbol, period=14):
def macd(df, symbol): def macd(df, symbol):
macd = df[symbol].ewm(span=12).mean() - df[symbol].ewm(span=26).mean() macd = df[symbol].ewm(span=12).mean() - df[symbol].ewm(span=26).mean()
k1 = f"macd" k1 = "macd"
k2 = k1 + "-signal" k2 = "macd_signal"
k3 = "macd_diff"
df[k1] = macd df[k1] = macd
df[k2] = macd.rolling(9).mean() df[k2] = macd.rolling(9).mean()
return df[[k1, k2]] df[k3] = df[k1] - df[k2]
return df[[k1, k2, k3]]
def price_delta(df, symbol, period=1): def price_delta(df, symbol, period=1):
"""Calculate delta between previous day and today.""" """Calculate delta between previous day and today."""
df[f"{symbol}-diff({period})"] = df[symbol].diff(periods=period) k = f"diff_{period}"
df[k] = df[symbol].diff(periods=period)
return df[k]
def price_delta(df, symbol, period=1):
"""Calculate percentage change for period."""
k = f"pct_{period}"
df[k] = df[symbol].pct_change(periods=period)
df[k] = df[k].shift(-period)
return df[k]
def test_indicators(): def test_indicators():
@ -135,4 +145,3 @@ def test_indicators():
df[symbol].plot(ax=axes[0], title="JPM price action") df[symbol].plot(ax=axes[0], title="JPM price action")
df[["JPM-macd", "JPM-macd-signal"]].plot(ax=axes[1]) df[["JPM-macd", "JPM-macd-signal"]].plot(ax=axes[1])
plt.savefig('figure_5.png') plt.savefig('figure_5.png')