"""
This is an algorithm.... copy past the code to a new algorithm to test it....
"""
import quantopian.algorithm as algo
from quantopian.pipeline import Pipeline
from quantopian.pipeline.data.builtin import USEquityPricing
from quantopian.pipeline import factors, filters, classifiers
import pandas as pd
def Q5US():
return filters.make_us_equity_universe(
target_size=5,
rankby=factors.AverageDollarVolume(window_length=200),
mask=filters.default_us_equity_universe_mask(),
groupby=classifiers.fundamentals.Sector(),
max_group_weight=0.3,
smoothing_func=lambda f: f.downsample('month_start'),
)
UNIVERS = Q5US()
BARS_VOLUME_PER_DAY = 10
BARS_DOLLAR_PER_DAY = 10
BACKWARD_MINUTES_CREATE = 4500
BACKWARD_MINUTES_DAY = 450
def initialize(context):
"""
Called once at the start of the algorithm.
"""
context.FTD = True
context.bars_list = []
context.bars_created = {}
# Rebalance every day, 1 hour after market open.
algo.schedule_function(
rebalance,
algo.date_rules.every_day(),
algo.time_rules.market_open(hours=1),
)
# Record tracking variables at the end of each day.
algo.schedule_function(
record_vars,
algo.date_rules.every_day(),
algo.time_rules.market_close(),
)
# Create our dynamic stock selector.
algo.attach_pipeline(make_pipeline(), 'pipeline')
def make_pipeline():
"""
A function to create our dynamic stock selector (pipeline). Documentation
on pipeline can be found here:
https://www.quantopian.com/help#pipeline-title
"""
# Base universe set to the QTradableStocksUS
base_universe = UNIVERS
# Factor of yesterday's close price.
yesterday_close = USEquityPricing.close.latest
pipe = Pipeline(
columns={
'close': yesterday_close,
},
screen=base_universe
)
return pipe
def before_trading_start(context, data):
"""
Called every day before market open.
"""
context.output = algo.pipeline_output('pipeline')
# These are the securities that we are interested in trading each day.
context.security_list = context.output.index
if context.FTD:
print "first trading day, creating bars dataframes and thresholds"
context.FTD = False
print type(context.security_list.values)
idx = pd.MultiIndex.from_product([[],[]],
names=['Equities', 'Dates'])
col = ['open','high','low','close','volume','dollar','last_date']
context.dollar_bars = pd.DataFrame( object, idx, col)
col = ['open','high','low','close','volume','last_date']
context.volume_bars = pd.DataFrame( object, idx, col)
### compute the volume and price average of last 100 days
context.volume_bars_threshold = {}
context.dollar_bars_threshold = {}
for equity in context.security_list.values:
vol = data.history(equity, 'volume', 100, '1d')
price = data.history(equity, 'high', 100, '1d')
context.volume_bars_threshold[equity] = vol.min() / BARS_VOLUME_PER_DAY
context.dollar_bars_threshold[equity] = (vol.values * price.values).min() / BARS_DOLLAR_PER_DAY
context.bars_created[equity] = False
context.bars_list.append(equity)
#print(equity,context.volume_bars_threshold[equity])
##### TODO : if a new equity popup.... one need to add it.....
print context.bars_list
###Create the bars for equities which bars have not been created yet
for equity in context.bars_list:
if context.bars_created[equity]==False:
print("creating bars:",equity)
open_price = data.history(equity, 'open', BACKWARD_MINUTES_CREATE, '1m')
high = data.history(equity, 'high', BACKWARD_MINUTES_CREATE, '1m')
low = data.history(equity, 'low', BACKWARD_MINUTES_CREATE, '1m')
close_price = data.history(equity, 'close',BACKWARD_MINUTES_CREATE, '1m')
volume = data.history(equity, 'volume', BACKWARD_MINUTES_CREATE, '1m')
dollar = volume.values*(high.values+low.values)/2
idx = 0
while context.bars_created[equity]==False and idx < BACKWARD_MINUTES_CREATE:
if open_price.values[idx]==open_price.values[idx]:
create_new_volume_bar(context.volume_bars,
equity,
volume.index[idx],
open_price.values[idx],
close_price.values[idx],
low.values[idx],
high.values[idx],
volume.values[idx])
create_new_dollar_bar(context.dollar_bars,
equity,
volume.index[idx],
open_price.values[idx],
close_price.values[idx],
low.values[idx],
high.values[idx],
volume.values[idx],
dollar[idx])
context.bars_created[equity] = True
idx += 1
if context.bars_created[equity] == True:
update_volume_bar(context.volume_bars,
equity,
volume.index[idx-1],
volume.index,
open_price.values,
close_price.values,
low.values,
high.values,
volume.values,
idx,
BACKWARD_MINUTES_CREATE,
context.volume_bars_threshold[equity])
update_dollar_bar(context.dollar_bars,
equity,
volume.index[idx-1],
volume.index,
open_price.values,
close_price.values,
low.values,
high.values,
volume.values,
dollar,
idx,
BACKWARD_MINUTES_CREATE,
context.dollar_bars_threshold[equity])
print(equity,"bar constructed")
### if an equity bar exist update the bars with previous day data
else:
print(equity,"bar exist, updating")
open_price = data.history(equity, 'open', BACKWARD_MINUTES_DAY, '1m')
high = data.history(equity, 'high', BACKWARD_MINUTES_DAY, '1m')
low = data.history(equity, 'low', BACKWARD_MINUTES_DAY, '1m')
close_price = data.history(equity, 'close',BACKWARD_MINUTES_DAY, '1m')
volume = data.history(equity, 'volume', BACKWARD_MINUTES_DAY, '1m')
dollar = volume.values*(high.values+low.values)/2
volume_date_index = context.volume_bars.loc[equity].index[-1]
dollar_date_index = context.dollar_bars.loc[equity].index[-1]
idx_volume = 0
idx_dollar = 0
while idx_volume < BACKWARD_MINUTES_DAY:
##print(volume_date_index,open_price.index[idx_volume])
if context.volume_bars.loc[equity].values[-1][5] == open_price.index[idx_volume]:
idx_volume += 1
break
idx_volume += 1
while idx_dollar < BACKWARD_MINUTES_DAY:
if context.dollar_bars.loc[equity].values[-1][6] == open_price.index[idx_dollar]:
idx_dollar += 1
break
idx_dollar += 1
update_volume_bar(context.volume_bars,
equity,
volume_date_index,
volume.index,
open_price.values,
close_price.values,
low.values,
high.values,
volume.values,
idx_volume,
BACKWARD_MINUTES_DAY,
context.volume_bars_threshold[equity])
update_dollar_bar(context.dollar_bars,
equity,
dollar_date_index,
volume.index,
open_price.values,
close_price.values,
low.values,
high.values,
volume.values,
dollar,
idx_dollar,
BACKWARD_MINUTES_DAY,
context.dollar_bars_threshold[equity])
print "done"
### here one should remove "too old bars" and "equitity not anymore tradable" to decrease memory usage.
def update_volume_bar(volume_bars,
equity,
start_bar_index,
dates_arr,
open_price_arr,
close_price_arr,
low_arr,
high_arr,
volume_arr,
start_idx,
end_idx,
threshold):
idx = start_idx
bar_index = start_bar_index
tot = volume_bars.loc[(equity,bar_index),'volume']
while idx < end_idx:
if open_price_arr[idx]==open_price_arr[idx]:
tot += volume_arr[idx]
if tot>threshold and abs(tot-volume_arr[idx]-threshold)<abs(tot-threshold):
#creat a new bar
bar_index = dates_arr[idx]
tot = volume_arr[idx]
create_new_volume_bar(volume_bars,
equity,
bar_index,
open_price_arr[idx],
close_price_arr[idx],
low_arr[idx],
high_arr[idx],
volume_arr[idx])
else:
#add to this bar
add_minute_to_volume_bar(volume_bars,
equity,
bar_index,
close_price_arr[idx],
low_arr[idx],
high_arr[idx],
volume_arr[idx],
dates_arr[idx])
else:
volume_bars[(equity,bar_index),'last_date'] = dates_arr[idx]
idx+=1
def update_dollar_bar(dollar_bars,
equity,
start_bar_index,
dates_arr,
open_price_arr,
close_price_arr,
low_arr,
high_arr,
volume_arr,
dollar_arr,
start_idx,
end_idx,
threshold):
idx = start_idx
bar_index = start_bar_index
tot = dollar_bars.loc[(equity,bar_index),'volume']
while idx < end_idx:
if open_price_arr[idx]==open_price_arr[idx]:
tot += dollar_arr[idx]
if tot>threshold and abs(tot-volume_arr[idx]-threshold)<abs(tot-threshold):
#creat a new bar
bar_index = dates_arr[idx]
tot = volume_arr[idx]
create_new_dollar_bar(dollar_bars,
equity,
bar_index,
open_price_arr[idx],
close_price_arr[idx],
low_arr[idx],
high_arr[idx],
volume_arr[idx],
dollar_arr[idx])
else:
#add to this bar
add_minute_to_dollar_bar(dollar_bars,
equity,
bar_index,
close_price_arr[idx],
low_arr[idx],
high_arr[idx],
volume_arr[idx],
dollar_arr[idx],
dates_arr[idx])
else:
dollar_bars[(equity,bar_index),'last_date'] = dates_arr[idx]
idx+=1
def create_new_volume_bar(volume_bars,equity,date,open_price,close_price,
low,high,volume):
volume_bars.loc[(equity, date),'open'] = open_price
volume_bars.loc[(equity, date),'close'] = close_price
volume_bars.loc[(equity, date),'high'] = high
volume_bars.loc[(equity, date),'low'] = low
volume_bars.loc[(equity, date),'volume'] = volume
volume_bars.loc[(equity, date),'last_date'] = date
def add_minute_to_volume_bar(volume_bars,equity,date,close_price,
low,high,volume,last_date):
volume_bars.loc[(equity, date),'close'] = close_price
if volume_bars.loc[(equity, date),'high'] < high:
volume_bars.loc[(equity, date),'high'] = high
if volume_bars.loc[(equity, date),'low'] > low:
volume_bars.loc[(equity, date),'low'] = low
volume_bars.loc[(equity, date),'volume'] += volume
volume_bars.loc[(equity, date),'last_date'] = last_date
def create_new_dollar_bar(dollar_bars,equity,date,open_price,close_price,
low,high,volume,dollar):
dollar_bars.loc[(equity, date),'open'] = open_price
dollar_bars.loc[(equity, date),'close'] = close_price
dollar_bars.loc[(equity, date),'high'] = high
dollar_bars.loc[(equity, date),'low'] = low
dollar_bars.loc[(equity, date),'volume'] = volume
dollar_bars.loc[(equity, date),'dollar'] = dollar
dollar_bars.loc[(equity, date),'last_date'] = date
def add_minute_to_dollar_bar(dollar_bars,equity,date,close_price,
low,high,volume,dollar,last_date):
dollar_bars.loc[(equity, date),'close'] = close_price
if dollar_bars.loc[(equity, date),'high'] < high:
dollar_bars.loc[(equity, date),'high'] = high
if dollar_bars.loc[(equity, date),'low'] > low:
dollar_bars.loc[(equity, date),'low'] = low
dollar_bars.loc[(equity, date),'volume'] += volume
dollar_bars.loc[(equity, date),'dollar'] += dollar
dollar_bars.loc[(equity, date),'last_date'] = last_date
def rebalance(context, data):
"""
Execute orders according to our schedule_function() timing.
"""
pass
def record_vars(context, data):
"""
Plot variables at the end of each day.
"""
def handle_data(context, data):
"""
Called every minute.
"""
pass