Skip to content

Instantly share code, notes, and snippets.

@sshariff01
Last active July 1, 2019 05:05
Show Gist options
  • Save sshariff01/6c6ec2086072aa2c57aa6ccd26dc4d72 to your computer and use it in GitHub Desktop.
Save sshariff01/6c6ec2086072aa2c57aa6ccd26dc4d72 to your computer and use it in GitHub Desktop.
ML4T - Project 6
"""
Student Name: Shoabe Shariff
GT User ID: sshariff3
GT ID: 903272097
"""
import pandas as pd
import numpy as np
import datetime as dt
import os
from util import get_data, plot_data
import matplotlib.pyplot as plt
import pdb
def author():
return 'sshariff3'
def illustrate_indicators(symbols = ['JPM'], start_date = dt.datetime(2008, 1, 1), end_date = dt.datetime(2009, 12, 31)):
prices = get_data(symbols, pd.date_range(start_date, end_date), addSPY=False).dropna(axis=0)
plot_data(calculate_momentum(prices), title='Technical Indicator 1: Momentum', xlabel='Date', ylabel='Momentum')
plot_data(calculate_bollinger_bands(prices), title='Technical Indicator 2: Bollinger Bands', xlabel='Date', ylabel='Price')
plot_data(calculate_sma(prices), title='Technical Indicator 3: Simple Moving Average (SMA)', xlabel='Date', ylabel='Normalized Price')
plot_data(calculate_macd(prices), title='Technical Indicator 4: Moving Average Convergence Divergence (MACD)', xlabel='Date', ylabel='Price')
"""
Technical Indicator 1 - Momentum
momentum[t] = price[t] / price[t-n]
* n = 10
"""
def calculate_momentum(prices):
df_temp = prices.copy()
df_temp[1:] = (df_temp[10:] / df_temp[:-10].values) - 1
df_temp.iloc[0:10] = np.nan
return df_temp
"""
Technical Indicator 2 - Bollinger Bands
1. Compute rolling mean
2. Compute rolling std deviation
3. Compute upper and lower bands
* window size = 20
"""
def calculate_bollinger_bands(prices):
rolling_mean = get_rolling_mean(prices['JPM'], window_size=20)
rolling_std = get_rolling_std(prices['JPM'], window_size=20)
upper_band, lower_band = get_bollinger_bands(rolling_mean, rolling_std)
rolling_mean = rolling_mean.to_frame('Rolling Mean')
rolling_std = rolling_std.to_frame('Rolling Std')
upper_band = upper_band.to_frame('Upper Band')
lower_band = lower_band.to_frame('Lower Band')
bollinger_band = (prices['JPM'] - rolling_mean['Rolling Mean']) / (2 * rolling_std['Rolling Std'])
bollinger_band = bollinger_band.to_frame('Bollinger Band')
df_temp = prices.join(rolling_mean).join(upper_band).join(lower_band).join(bollinger_band)
return df_temp
def get_rolling_mean(values, window_size):
return pd.rolling_mean(values, window=window_size)
def get_rolling_std(values, window_size):
return pd.rolling_std(values, window=window_size)
def get_bollinger_bands(rm, rstd):
upper_band = rm + rstd*2
lower_band = rm - rstd*2
return upper_band, lower_band
"""
Technical Indicator 3 - SMA
1. Plot SMA
2. Plot Price
3. Plot Price/SMA
* moving window size = 10
"""
def calculate_sma(prices):
normalized_prices = prices / prices.ix[0,:]
rolling_mean = get_rolling_mean(normalized_prices['JPM'], window_size=10)
rolling_mean = rolling_mean.to_frame('SMA')
df_temp = normalized_prices.join(rolling_mean)
df_temp['JPM/SMA'] = df_temp['JPM'] / df_temp['SMA'] - 1
return df_temp
"""
Technical Indicator 4 - MACD
MACD = (12 period EMA) - (26 period EMA)
Sources:
* MACD - https://www.investopedia.com/terms/m/macd.asp
* DataFrame EWM - http://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.ewm.html
"""
def calculate_macd(prices):
ema_12 = prices.ewm(span=12).mean()
ema_12 = ema_12.rename(columns={'JPM': 'JPM 12-period Exp Moving Avg'})
ema_26 = prices.ewm(span=26).mean()
ema_26 = ema_26.rename(columns={'JPM': 'JPM 26-period Exp Moving Avg'})
df_temp = ema_12.join(ema_26)
df_temp['MACD'] = df_temp['JPM 12-period Exp Moving Avg'] - df_temp['JPM 26-period Exp Moving Avg']
df_temp['Signal Line'] = df_temp['MACD'].ewm(span=9).mean()
return df_temp
if __name__ == "__main__":
illustrate_indicators()
"""
Student Name: Shoabe Shariff
GT User ID: sshariff3
GT ID: 903272097
"""
import pandas as pd
import numpy as np
import datetime as dt
import os
from util import get_data, plot_data
from indicators import calculate_momentum, calculate_bollinger_bands, calculate_sma, calculate_macd
from marketsimcode import compute_portvals
import matplotlib.pyplot as plt
import pdb
def testPolicy(symbol = "AAPL", sd=dt.datetime(2010, 1, 1), ed=dt.datetime(2011, 12, 31), sv = 100000):
adjusted_close_prices = get_data([symbol], pd.date_range(sd, ed), addSPY=False).dropna()
adjusted_close_prices.index.name = 'Date'
momentum = calculate_momentum(adjusted_close_prices).rename(columns={symbol: 'Momentum'})
bollinger_bands = calculate_bollinger_bands(adjusted_close_prices).drop('JPM', axis=1)
sma = calculate_sma(adjusted_close_prices)['JPM/SMA']
portfolio = {}
portfolio['Shares'] = 0
indicators = adjusted_close_prices.join(momentum).join(bollinger_bands).join(sma)
return indicators.apply(lambda x: generate_orders(x, portfolio), axis=1, raw=False)
def generate_orders(indicators, portfolio):
order = 0
if portfolio['firstRun'] == True:
portfolio['firstRun'] = False
indicators['Orders'] = 0
return indicators['Orders']
if indicators['JPM/SMA'] < 0 and indicators['Bollinger Band'] < 1 and indicators['Momentum'] < 0:
if portfolio['Shares'] < 1000: # BUY 1000 shares
order = 1000
portfolio['Shares'] = portfolio['Shares'] + 1000
elif indicators['JPM/SMA'] > 0 and indicators['Bollinger Band'] > -1 and indicators['Momentum'] > 0:
if portfolio['Shares'] > -1000: # SELL 1000 shares
order = -1000
portfolio['Shares'] = portfolio['Shares'] - 1000
elif indicators['JPM/SMA'] > 0.5 and indicators['Bollinger Band'] > 1 and indicators['Momentum'] < 0:
if portfolio['Shares'] > 0: # SELL 2000 shares
order = -2000
portfolio['Shares'] = portfolio['Shares'] - 2000
elif portfolio['Shares'] == 0: # SELL 1000 shares
order = -1000
portfolio['Shares'] = portfolio['Shares'] - 1000
elif indicators['Momentum'] < 0:
if portfolio['Shares'] >= 0: # SELL 1000 shares
order = -1000
portfolio['Shares'] = portfolio['Shares'] - 1000
elif indicators['Momentum'] > 0:
if portfolio['Shares'] >= 0: # SELL 1000 shares
order = -1000
portfolio['Shares'] = portfolio['Shares'] - 1000
indicators['Orders'] = order
return indicators['Orders']
def compute_daily_returns(df):
daily_returns = df.copy()
daily_returns[1:] = (df[1:] / df[:-1].values) - 1
return daily_returns.ix[1:]
def report_metrics(port_vals, strategy):
daily_rets = compute_daily_returns(port_vals)
cr = (port_vals[-1]/port_vals[0]) - 1
adr = daily_rets.mean()
sddr = daily_rets.std()
print "Cumulative Return of {}: {}".format(strategy, cr)
print "Standard Deviation of {}: {}".format(strategy, sddr)
print "Average Daily Return of {}: {}".format(strategy, adr)
print
def test_sample_data(sd = dt.datetime(2008, 1, 1), ed = dt.datetime(2009, 12, 31)):
symbol = "JPM"
start_val = 100000
####
# Manual Strategy
####
df_trades = testPolicy(symbol=symbol, sd=sd, ed=ed, sv=start_val)
df_trades = df_trades.to_frame('Order')
manual_portvals = compute_portvals(df_trades, symbol, start_val=start_val, commission=9.95, impact=0.005)
report_metrics(manual_portvals, 'Manual Strategy')
manual_portvals = manual_portvals.to_frame('Manual Strategy')
normalized_manual_strategy = manual_portvals / manual_portvals.ix[0,:]
####
# Benchmark
####
benchmark_trades = df_trades.copy()
adjusted_close_prices = get_data([symbol], pd.date_range(sd, ed), addSPY=False).dropna()
adjusted_close_prices.index.name = 'Date'
first_transaction_date = adjusted_close_prices.index[adjusted_close_prices['JPM'] != 0][0]
benchmark_trades['Order'] = 0
benchmark_trades.loc[first_transaction_date]['Order'] = 1000
benchmark_portvals = compute_portvals(benchmark_trades, symbol, start_val=start_val, commission=9.95, impact=0.005)
report_metrics(benchmark_portvals, 'Benchmark')
benchmark_portvals = benchmark_portvals.to_frame('Benchmark')
normalized_benchmark = benchmark_portvals / benchmark_portvals.ix[0,:]
####
# Plot
####
df_temp = normalized_benchmark.join(normalized_manual_strategy)
ax = df_temp.plot(title='Manual Strategy vs Benchmark', fontsize=12, color=['green', 'red'])
ax.set_xlabel('Date')
ax.set_ylabel('Portfoio Value')
plt.show()
if __name__ == "__main__":
test_sample_data(sd = dt.datetime(2008, 1, 1), ed = dt.datetime(2009, 12, 31))
test_sample_data(sd = dt.datetime(2010, 1, 1), ed = dt.datetime(2011, 12, 31))
"""MC2-P1: Market simulator.
Copyright 2018, Georgia Institute of Technology (Georgia Tech)
Atlanta, Georgia 30332
All Rights Reserved
Template code for CS 4646/7646
Georgia Tech asserts copyright ownership of this template and all derivative
works, including solutions to the projects assigned in this course. Students
and other users of this template code are advised not to share it with others
or to make it available on publicly viewable websites including repositories
such as github and gitlab. This copyright statement should not be removed
or edited.
We do grant permission to share solutions privately with non-students such
as potential employers. However, sharing with other current or future
students of CS 7646 is prohibited and subject to being investigated as a
GT honor code violation.
-----do not edit anything above this line---
Student Name: Shoabe Shariff
GT User ID: sshariff3
GT ID: 903272097
"""
import pandas as pd
import numpy as np
import datetime as dt
import os
from util import get_data, plot_data
import pdb
def author():
return 'sshariff3'
def compute_portvals(df_trades, symbol, start_val = 1000000, commission=9.95, impact=0.005):
# this is the function the autograder will call to test your code
# NOTE: orders_file may be a string, or it may be a file object. Your
# code should work correctly with either input
# TODO: Your code here
orders = df_trades.sort_index()
start_date = orders.index[0]
end_date = orders.index[-1]
adjusted_close_prices = get_data([symbol], pd.date_range(start_date, end_date), addSPY=False)
adjusted_close_prices.index.name = 'Date'
adjusted_close_prices['PORTFOLIO'] = 0
portfolio = dict.fromkeys([symbol], 0)
portfolio['CASH'] = start_val
return adjusted_close_prices.apply(lambda x: calculate_portfolio_value(x, orders, symbol, portfolio, commission, impact), axis=1, raw=False).dropna()
def calculate_portfolio_value(prices, orders_all, symbol, portfolio, commission, impact):
if prices.name in orders_all.index:
orders_for_the_day = orders_all.loc[orders_all.index == prices.name, ['Order']]
orders_for_the_day.apply(lambda x: update_portfolio(x, prices, symbol, portfolio, commission, impact), axis=1, raw=False)
prices['PORTFOLIO'] = portfolio['CASH'] # Initialize to cash holdings amount
for sym in portfolio.keys():
if sym == 'CASH':
continue
num_shares_in_portfolio = portfolio[sym]
prices['PORTFOLIO'] = prices['PORTFOLIO'] + num_shares_in_portfolio * prices[sym]
return prices['PORTFOLIO']
def update_portfolio(order, prices, purchase_symbol, portfolio, commission, impact):
trade_num_shares = order['Order']
stock_price = prices[purchase_symbol]
# Update Portfolio Shares and Cash Holdings
if trade_num_shares > 0:
portfolio[purchase_symbol] = portfolio[purchase_symbol] + trade_num_shares
# Apply market impact - Price goes up by impact prior to purchase
stock_price = stock_price * (1 + impact)
portfolio['CASH'] = portfolio['CASH'] - trade_num_shares * stock_price
# Apply commission - To be applied on every transaction, regardless of BUY or SELL
portfolio['CASH'] = portfolio['CASH'] - commission
elif trade_num_shares < 0:
trade_num_shares = -1 * trade_num_shares
portfolio[purchase_symbol] = portfolio[purchase_symbol] - trade_num_shares
# Apply market impact - Price goes down by impact prior to sell
stock_price = stock_price * (1 - impact)
portfolio['CASH'] = portfolio['CASH'] + trade_num_shares * stock_price
# Apply commission - To be applied on every transaction, regardless of BUY or SELL
portfolio['CASH'] = portfolio['CASH'] - commission
if __name__ == "__main__":
compute_portvals()
# test_code()
"""
Student Name: Shoabe Shariff
GT User ID: sshariff3
GT ID: 903272097
"""
import pandas as pd
import numpy as np
import datetime as dt
import os
from util import get_data, plot_data
from marketsimcode import compute_portvals
import matplotlib.pyplot as plt
import pdb
def testPolicy(symbol = "AAPL", sd=dt.datetime(2010, 1, 1), ed=dt.datetime(2011, 12, 31), sv = 100000):
adjusted_close_prices = get_data([symbol], pd.date_range(sd, ed), addSPY=False).dropna()
adjusted_close_prices.index.name = 'Date'
adjusted_close_prices = adjusted_close_prices.rename(columns={symbol: 'Today'})
adjusted_close_prices['Next'] = adjusted_close_prices['Today'].shift(-1)
portfolio = {}
portfolio['Shares'] = 0
portfolio['firstRun'] = True
current_holdings = 0
return adjusted_close_prices.apply(lambda x: generate_orders(x, portfolio), axis=1, raw=False)
def generate_orders(data, portfolio):
if portfolio['firstRun']:
portfolio['firstRun'] = False
data['Orders'] = 0
return data['Orders']
future_price_increase = data['Next'] - data['Today']
order = 0
if future_price_increase > 0 and portfolio['Shares'] < 1000:
order = 1000 - portfolio['Shares']
portfolio['Shares'] = 1000
elif future_price_increase < 0 and portfolio['Shares'] > -1000:
order = -1000 - portfolio['Shares']
portfolio['Shares'] = -1000
data['Orders'] = order
return data['Orders']
def compute_daily_returns(df):
daily_returns = df.copy()
daily_returns[1:] = (df[1:] / df[:-1].values) - 1
return daily_returns.ix[1:]
def report_metrics(port_vals, strategy):
daily_rets = compute_daily_returns(port_vals)
cr = (port_vals[-1]/port_vals[0]) - 1
adr = daily_rets.mean()
sddr = daily_rets.std()
print "Cumulative Return of {}: {}".format(strategy, cr)
print "Standard Deviation of {}: {}".format(strategy, sddr)
print "Average Daily Return of {}: {}".format(strategy, adr)
print
if __name__ == "__main__":
symbol = "JPM"
sd = dt.datetime(2008, 1, 1)
ed = dt.datetime(2009, 12, 31)
# sd = dt.datetime(2010, 1, 1)
# ed = dt.datetime(2011, 12, 31)
start_val = 100000
####
# Theoretically Optimal Strategy
####
df_trades = testPolicy(symbol=symbol, sd=sd, ed=ed, sv=start_val)
df_trades = df_trades.to_frame('Order')
theoretically_optimal_portvals = compute_portvals(df_trades, symbol, start_val=start_val, commission=0., impact=0.)
report_metrics(theoretically_optimal_portvals, 'Theoretically Optimal Strategy')
theoretically_optimal_portvals = theoretically_optimal_portvals.to_frame('Theoretically Optimal Strategy')
normalized_optimal_strategy = theoretically_optimal_portvals / theoretically_optimal_portvals.ix[0,:]
####
# Benchmark
####
benchmark_trades = df_trades.copy()
adjusted_close_prices = get_data([symbol], pd.date_range(sd, ed), addSPY=False).dropna()
adjusted_close_prices.index.name = 'Date'
first_transaction_date = adjusted_close_prices.index[adjusted_close_prices['JPM'] != 0][0]
benchmark_trades['Order'] = 0
benchmark_trades.loc[first_transaction_date]['Order'] = 1000
benchmark_portvals = compute_portvals(benchmark_trades, symbol, start_val=start_val, commission=0., impact=0.)
report_metrics(benchmark_portvals, 'Benchmark')
benchmark_portvals = benchmark_portvals.to_frame('Benchmark')
normalized_benchmark = benchmark_portvals / benchmark_portvals.ix[0,:]
####
# Plot
####
df_temp = normalized_benchmark.join(normalized_optimal_strategy)
ax = df_temp.plot(title='Theoretically Optimal Strategy vs Benchmark', fontsize=12, color=['green', 'red'])
ax.set_xlabel('Date')
ax.set_ylabel('Portfoio Value')
plt.show()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment