Compare commits
2 Commits
85a9c4fcb3
...
4679910374
| Author | SHA1 | Date | |
|---|---|---|---|
| 4679910374 | |||
| 1798e9569e |
@@ -75,16 +75,28 @@ def get_portfolio_value(holding, prices):
|
|||||||
def handle_order(date, order, holding, prices, commission, impact):
|
def handle_order(date, order, holding, prices, commission, impact):
|
||||||
"""Process the order."""
|
"""Process the order."""
|
||||||
symbol, order, shares = order
|
symbol, order, shares = order
|
||||||
assert(shares > 0) # Can only buy or sell positive amount of shares.
|
if shares == 0 and order == "":
|
||||||
|
return # empty order
|
||||||
|
if pd.isnull(shares):
|
||||||
|
return # shares is nan
|
||||||
|
|
||||||
|
# Allow indicating buying and selling via shares. If shares is positive we
|
||||||
|
# buy and if it is negative we sell.
|
||||||
|
if shares > 0 and order == "":
|
||||||
|
order = "BUY"
|
||||||
|
elif shares < 0 and order == "":
|
||||||
|
order = "SELL"
|
||||||
|
shares = abs(shares)
|
||||||
|
|
||||||
adj_closing_price = prices[symbol]
|
adj_closing_price = prices[symbol]
|
||||||
cost = shares * adj_closing_price
|
cost = shares * adj_closing_price
|
||||||
# Charge commission and deduct impact penalty
|
# Charge commission and deduct impact penalty
|
||||||
holding['cash'] -= (commission + impact * adj_closing_price * shares)
|
holding['cash'] -= (commission + impact * adj_closing_price * shares)
|
||||||
if order == "BUY":
|
if order.upper() == "BUY":
|
||||||
# print(f"Buy {shares:6} of {symbol:4} on {date}")
|
# print(f"Buy {shares:6} of {symbol:4} on {date}")
|
||||||
holding['cash'] -= cost
|
holding['cash'] -= cost
|
||||||
holding[symbol] += shares
|
holding[symbol] += shares
|
||||||
elif order == "SELL":
|
elif order.upper() == "SELL":
|
||||||
# print(f"Sell {shares:6} of {symbol:4} on {date}")
|
# print(f"Sell {shares:6} of {symbol:4} on {date}")
|
||||||
holding['cash'] += cost
|
holding['cash'] += cost
|
||||||
holding[symbol] -= shares
|
holding[symbol] -= shares
|
||||||
|
|||||||
@@ -25,10 +25,8 @@ class BenchmarkStrategy:
|
|||||||
orders["Symbol"] = symbol
|
orders["Symbol"] = symbol
|
||||||
orders["Order"] = ""
|
orders["Order"] = ""
|
||||||
orders["Shares"] = 0
|
orders["Shares"] = 0
|
||||||
|
|
||||||
orders.iloc[0] = [symbol, "BUY", 1000]
|
orders.iloc[0] = [symbol, "BUY", 1000]
|
||||||
orders.iloc[-1] = [symbol, "SELL", 1000]
|
orders.iloc[-1] = [symbol, "SELL", -1000]
|
||||||
orders = orders[orders["Shares"] != 0]
|
|
||||||
|
|
||||||
if self.verbose:
|
if self.verbose:
|
||||||
print(type(orders)) # it better be a DataFrame!
|
print(type(orders)) # it better be a DataFrame!
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import datetime as dt
|
import datetime as dt
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
import util as ut
|
import util
|
||||||
|
import indicators
|
||||||
|
|
||||||
|
|
||||||
class ManualStrategy:
|
class ManualStrategy:
|
||||||
@@ -20,7 +21,7 @@ class ManualStrategy:
|
|||||||
# example usage of the old backward compatible util function
|
# example usage of the old backward compatible util function
|
||||||
syms = [symbol]
|
syms = [symbol]
|
||||||
dates = pd.date_range(sd, ed)
|
dates = pd.date_range(sd, ed)
|
||||||
prices_all = ut.get_data(syms, dates) # automatically adds SPY
|
prices_all = util.get_data(syms, dates) # automatically adds SPY
|
||||||
prices = prices_all[syms] # only portfolio symbols
|
prices = prices_all[syms] # only portfolio symbols
|
||||||
# prices_SPY = prices_all['SPY'] # only SPY, for comparison later
|
# prices_SPY = prices_all['SPY'] # only SPY, for comparison later
|
||||||
if self.verbose:
|
if self.verbose:
|
||||||
@@ -28,31 +29,60 @@ class ManualStrategy:
|
|||||||
|
|
||||||
# example use with new colname
|
# example use with new colname
|
||||||
# automatically adds SPY
|
# automatically adds SPY
|
||||||
volume_all = ut.get_data(syms, dates, colname="Volume")
|
volume_all = util.get_data(syms, dates, colname="Volume")
|
||||||
volume = volume_all[syms] # only portfolio symbols
|
volume = volume_all[syms] # only portfolio symbols
|
||||||
# volume_SPY = volume_all['SPY'] # only SPY, for comparison later
|
# volume_SPY = volume_all['SPY'] # only SPY, for comparison later
|
||||||
if self.verbose:
|
if self.verbose:
|
||||||
print(volume)
|
print(volume)
|
||||||
|
|
||||||
|
def macd_strat(self, macd, orders):
|
||||||
|
|
||||||
|
def strat(ser):
|
||||||
|
m = macd.loc[ser.index]
|
||||||
|
prev_macd, prev_signal = m.iloc[0]
|
||||||
|
cur_macd, cur_signal = m.iloc[1]
|
||||||
|
shares = 0
|
||||||
|
if cur_macd < -1 and prev_macd < prev_signal and cur_macd > cur_signal:
|
||||||
|
if self.holding == 0:
|
||||||
|
shares = 1000
|
||||||
|
elif self.holding == -1000:
|
||||||
|
shares = 2000
|
||||||
|
elif cur_macd > 1 and prev_macd > prev_signal and cur_macd < cur_signal:
|
||||||
|
if self.holding == 0:
|
||||||
|
shares = -1000
|
||||||
|
elif self.holding == 1000:
|
||||||
|
shares = -2000
|
||||||
|
self.holding += shares
|
||||||
|
return shares
|
||||||
|
|
||||||
|
orders['Shares'] = orders['Shares'].rolling(2).apply(strat)
|
||||||
|
|
||||||
|
|
||||||
# this method should use the existing policy and test it against new data
|
# 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),
|
||||||
sv=10000):
|
sv=10000):
|
||||||
dates = pd.date_range(sd, ed)
|
|
||||||
prices = ut.get_data([symbol], dates) # automatically adds SPY
|
self.holding = 0
|
||||||
orders = pd.DataFrame(index=prices.index)
|
df = util.get_data([symbol], pd.date_range(sd, ed))
|
||||||
|
df.drop(columns=["SPY"], inplace=True)
|
||||||
|
macd = indicators.macd(df, symbol)
|
||||||
|
|
||||||
|
orders = pd.DataFrame(index=df.index)
|
||||||
orders["Symbol"] = symbol
|
orders["Symbol"] = symbol
|
||||||
orders["Order"] = ""
|
orders["Order"] = ""
|
||||||
orders["Shares"] = 0
|
orders["Shares"] = 0
|
||||||
|
|
||||||
|
self.macd_strat(macd, orders)
|
||||||
|
|
||||||
# here we build a fake set of trades
|
# here we build a fake set of trades
|
||||||
orders.iloc[0] = [symbol, "BUY", 1000]
|
# orders.iloc[0] = [symbol, "BUY", 1000]
|
||||||
orders.iloc[40] = [symbol, "SELL", 1000]
|
# orders.iloc[40] = [symbol, "SELL", 1000]
|
||||||
orders.iloc[41] = [symbol, "BUY", 1000]
|
# orders.iloc[41] = [symbol, "BUY", 1000]
|
||||||
orders.iloc[60] = [symbol, "SELL", 2000]
|
# orders.iloc[60] = [symbol, "SELL", 2000]
|
||||||
orders.iloc[61] = [symbol, "BUY", 2000]
|
# orders.iloc[61] = [symbol, "BUY", 2000]
|
||||||
orders.iloc[-1] = [symbol, "SELL", 1000]
|
# orders.iloc[-1] = [symbol, "SELL", 1000]
|
||||||
orders = orders[orders["Shares"] != 0]
|
# orders = orders[orders["Shares"] != 0]
|
||||||
return orders
|
return orders
|
||||||
|
|
||||||
|
|||||||
@@ -9,22 +9,6 @@ from BenchmarkStrategy import BenchmarkStrategy
|
|||||||
from ManualStrategy import ManualStrategy
|
from ManualStrategy import ManualStrategy
|
||||||
|
|
||||||
|
|
||||||
def macd_strat(macd):
|
|
||||||
def strat(x):
|
|
||||||
print(x)
|
|
||||||
|
|
||||||
macd['macd_trigger'] = macd.rolling(2).apply(strat)
|
|
||||||
|
|
||||||
# for i, row in macd.iterrows():
|
|
||||||
# if i == 0:
|
|
||||||
# continue
|
|
||||||
# print(row)
|
|
||||||
# prev_macd, prev_signal, _ = row
|
|
||||||
# cur_macd, cur_signal, _ = row
|
|
||||||
# if cur_macd < -.5 and (prev_macd < prev_signal) \
|
|
||||||
# and (cur_macd > cur_signal):
|
|
||||||
# macd.iloc[i]['macd_buy_sell'] = 1
|
|
||||||
|
|
||||||
def experiment1():
|
def experiment1():
|
||||||
symbol = "JPM"
|
symbol = "JPM"
|
||||||
start_value = 10000
|
start_value = 10000
|
||||||
@@ -32,46 +16,33 @@ def experiment1():
|
|||||||
ed = dt.datetime(2009, 12, 31)
|
ed = dt.datetime(2009, 12, 31)
|
||||||
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)
|
||||||
# df = pd.DataFrame(index=df.index)
|
|
||||||
|
|
||||||
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)
|
||||||
|
df["Orders Benchmark"] = orders["Shares"]
|
||||||
|
|
||||||
ms = ManualStrategy()
|
ms = ManualStrategy()
|
||||||
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"]
|
||||||
|
|
||||||
# indicators.price_sma(df, symbol, 21)
|
# indicators.price_sma(df, symbol, 21)
|
||||||
# sma = indicators.sma(df, symbol, [9, 21])
|
# sma = indicators.sma(df, symbol, [9, 21])
|
||||||
# rsi = indicators.rsi(df, symbol)
|
# rsi = indicators.rsi(df, symbol)
|
||||||
macd = indicators.macd(df, symbol).copy()
|
macd = indicators.macd(df, symbol).copy()
|
||||||
# macd_strat(macd)
|
|
||||||
|
|
||||||
fig, ax = plt.subplots(2, sharex=True)
|
fig, ax = plt.subplots(4, sharex=True)
|
||||||
df[symbol].plot(ax=ax[0])
|
df[symbol].plot(ax=ax[0])
|
||||||
# sma.plot(ax=ax[0])
|
macd.plot(ax=ax[3])
|
||||||
macd.plot(ax=ax[1])
|
df[["Benchmark", "Manual"]].plot(ax=ax[1])
|
||||||
# macd.iloc[:,0].plot(ax=ax[1])
|
df[["Orders Benchmark", "Orders Manual"]].plot(ax=ax[2])
|
||||||
# rsi.plot(ax=ax[2])
|
|
||||||
# df[["Benchmark", "Manual"]].plot(ax=ax[3])
|
|
||||||
|
|
||||||
# XXX: Plot where we buy and sell.
|
for a in ax:
|
||||||
|
a.grid()
|
||||||
for a in ax: a.grid()
|
|
||||||
multi = MultiCursor(fig.canvas, ax, color='r', lw=0.5)
|
multi = MultiCursor(fig.canvas, ax, color='r', lw=0.5)
|
||||||
plt.show()
|
plt.show()
|
||||||
|
# plt.savefig('figure_1.png')
|
||||||
# df.plot(title="results", subplots=True)
|
|
||||||
#sd = dt.datetime(2008, 1, 1)
|
|
||||||
#ed = dt.datetime(2009, 12, 31)
|
|
||||||
#df = get_data([symbol], pd.date_range(sd, ed))
|
|
||||||
#df.drop(columns=["SPY"], inplace=True)
|
|
||||||
# df_orig = df.copy()
|
|
||||||
#df = indicators.normalize(df)
|
|
||||||
#indicators.price_sma(df, symbol, 21)
|
|
||||||
#df.plot(title="21 SMA and EMA")
|
|
||||||
#plt.show()
|
|
||||||
|
|
||||||
# You may use data from other symbols (such as SPY) to inform both your
|
# 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
|
# Manual Learner and Strategy Learner. The in-sample/development period is
|
||||||
@@ -79,63 +50,5 @@ def experiment1():
|
|||||||
# January 1, 2010 to December 31 2011.
|
# January 1, 2010 to December 31 2011.
|
||||||
|
|
||||||
|
|
||||||
class BlittedCursor:
|
|
||||||
"""
|
|
||||||
A cross hair cursor using blitting for faster redraw.
|
|
||||||
"""
|
|
||||||
def __init__(self, ax):
|
|
||||||
self.ax = ax
|
|
||||||
self.background = None
|
|
||||||
self.horizontal_line = ax.axhline(color='k', lw=0.8, ls='--')
|
|
||||||
self.vertical_line = ax.axvline(color='k', lw=0.8, ls='--')
|
|
||||||
# text location in axes coordinates
|
|
||||||
self.text = ax.text(0.72, 0.9, '', transform=ax.transAxes)
|
|
||||||
self._creating_background = False
|
|
||||||
ax.figure.canvas.mpl_connect('draw_event', self.on_draw)
|
|
||||||
|
|
||||||
def on_draw(self, event):
|
|
||||||
self.create_new_background()
|
|
||||||
|
|
||||||
def set_cross_hair_visible(self, visible):
|
|
||||||
need_redraw = self.horizontal_line.get_visible() != visible
|
|
||||||
self.horizontal_line.set_visible(visible)
|
|
||||||
self.vertical_line.set_visible(visible)
|
|
||||||
self.text.set_visible(visible)
|
|
||||||
return need_redraw
|
|
||||||
|
|
||||||
def create_new_background(self):
|
|
||||||
if self._creating_background:
|
|
||||||
# discard calls triggered from within this function
|
|
||||||
return
|
|
||||||
self._creating_background = True
|
|
||||||
self.set_cross_hair_visible(False)
|
|
||||||
self.ax.figure.canvas.draw()
|
|
||||||
self.background = self.ax.figure.canvas.copy_from_bbox(self.ax.bbox)
|
|
||||||
self.set_cross_hair_visible(True)
|
|
||||||
self._creating_background = False
|
|
||||||
|
|
||||||
def on_mouse_move(self, event):
|
|
||||||
if self.background is None:
|
|
||||||
self.create_new_background()
|
|
||||||
if not event.inaxes:
|
|
||||||
need_redraw = self.set_cross_hair_visible(False)
|
|
||||||
if need_redraw:
|
|
||||||
self.ax.figure.canvas.restore_region(self.background)
|
|
||||||
self.ax.figure.canvas.blit(self.ax.bbox)
|
|
||||||
else:
|
|
||||||
self.set_cross_hair_visible(True)
|
|
||||||
# update the line positions
|
|
||||||
x, y = event.xdata, event.ydata
|
|
||||||
self.horizontal_line.set_ydata(y)
|
|
||||||
self.vertical_line.set_xdata(x)
|
|
||||||
self.text.set_text('x=%1.2f, y=%1.2f' % (x, y))
|
|
||||||
|
|
||||||
self.ax.figure.canvas.restore_region(self.background)
|
|
||||||
self.ax.draw_artist(self.horizontal_line)
|
|
||||||
self.ax.draw_artist(self.vertical_line)
|
|
||||||
self.ax.draw_artist(self.text)
|
|
||||||
self.ax.figure.canvas.blit(self.ax.bbox)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
experiment1()
|
experiment1()
|
||||||
|
|||||||
BIN
strategy_evaluation/figure_1.png
Normal file
BIN
strategy_evaluation/figure_1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 68 KiB |
3
strategy_evaluation/strategy_evaluation.md
Normal file
3
strategy_evaluation/strategy_evaluation.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# Report
|
||||||
|
|
||||||
|

|
||||||
Reference in New Issue
Block a user