We get it. We're working hard so you can eventually start doing that, so in the meanwhile, here's something that might quench your thirst. It's the basic framework for how to run, test, and optimize an algorithm over N number of parameters.
Trust me, it's super simple and easy to follow and will make your life a whole lot easier.
Let's say I want an algorithm that only longs AAPL and SPY but I don't know how much to hold in each security. I could try hitting 'build algorithm' 50 times in the IDE but that's tedious and my macbook can't open that many tabs. So what do I do?
The answer is easy: Create that same algorithm in Zipline and spin up 50 algorithm runs. Each run will have different parameters and because I can get the results of each run through Zipline, I can see exactly which parameter led to the best returns or Sharpe ratio.
"""
This cell is going to create the basic framework of the algorithm
"""
import zipline
import pytz
from datetime import datetime
import matplotlib.pyplot as pyplot
from collections import defaultdict
from zipline import TradingAlgorithm
from zipline.api import order_target, record, symbol, history, add_history
import numpy as np
#: NOTICE HOW THIS IS OUTSIDE INITIALIZE, BECAUSE IT IS, WE CAN REDFINE IT EVERYTIME WE REDINE INITIALIZE
aapl_weights = .50
spy_weights = .50
def initialize(context):
context.aapl = 24
context.spy = 8554
context.aapl_weights = aapl_weights
context.spy_weights = spy_weights
context.first_time = True
def handle_data(context, data):
#: Only order on the first bar
if context.first_time:
order_target_percent(context.aapl, context.aapl_weights)
order_target_percent(context.spy, context.spy_weights)
context.first_time = False
"""
This cell is going to load in the data, run the algorithm, and print out the Sharpe Ratio
"""
data = get_pricing(
['AAPL', 'SPY'],
start_date='2014-01-01',
end_date = '2015-02-15',
frequency='daily'
)
algo_obj = TradingAlgorithm(
initialize=initialize,
handle_data=handle_data
)
#: See this perf_manual object? I'm going to use that to get ending portfolio value
perf_manual = algo_obj.run(data.transpose(2,1,0))
#: Get the sharpe ratio
sharpe = (perf_manual.returns.mean()*252)/(perf_manual.returns.std() * np.sqrt(252))
print "The Sharpe ratio is %0.6f" % sharpe
Okay, look at the process above. What I'm going to do is take this same exact process and rerun it 25 times with different weights for AAPL and SPY. For the sake of this example, I'm going to generate weights that sum to > (1) and show you a really cool heatmap to go along with it.
aapl_weights = [weight for weight in np.arange(0, 1, .2)]
spy_weights = [weight for weight in np.arange(0, 1, .2)]
#: Create a dictionary to hold all the results of our algorithm run
all_sharpes = defaultdict(dict)
for aapl_weight in aapl_weights:
for spy_weight in spy_weights:
#: Redfine initialize with new weights
def initialize(context):
context.aapl = 24
context.spy = 8554
context.aapl_weights = aapl_weight
context.spy_weights = spy_weight
context.first_time = True
algo_obj = TradingAlgorithm(
initialize=initialize,
handle_data=handle_data
)
perf_manual = algo_obj.run(data.transpose(2,1,0))
sharpe = (perf_manual.returns.mean()*252)/(perf_manual.returns.std() * np.sqrt(252))
#: Add the result to our dict
all_sharpes[aapl_weight][spy_weight] = sharpe
all_sharpes = pd.DataFrame(all_sharpes)
all_sharpes.index.name = "SPY Weight"
all_sharpes.columns.name = "AAPL Weight"
import matplotlib.pyplot as pyplot
def heat_map(df):
"""
This creates our heatmap using our sharpe ratio dataframe
"""
fig = pyplot.figure()
ax = fig.add_subplot(111)
axim = ax.imshow(df.values,cmap = pyplot.get_cmap('RdYlGn'), interpolation = 'nearest')
ax.set_xlabel(df.columns.name)
ax.set_xticks(np.arange(len(df.columns)))
ax.set_xticklabels(list(df.columns))
ax.set_ylabel(df.index.name)
ax.set_yticks(np.arange(len(df.index)))
ax.set_yticklabels(list(df.index))
ax.set_title("Sharpe Ratios")
pyplot.colorbar(axim)
#: Plot our heatmap
heat_map(all_sharpes)
print all_sharpes
The best Sharpe ratio seems to come from an AAPL weight of 0.8 and a SPY weight of 0.2.
Rinse, repeat. Plug and chug with your own algorithms. Just make sure to replace the initialize
, handle_data
, and get_pricing
methods with your own data.