Skip to content

Instantly share code, notes, and snippets.

@umitanuki
Created March 22, 2016 21:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save umitanuki/23b0f2df585fa4e24912 to your computer and use it in GitHub Desktop.
Save umitanuki/23b0f2df585fa4e24912 to your computer and use it in GitHub Desktop.
Turtle in quantopian
# For this example, we're going to write a simple momentum script.
# When the stock goes up quickly, we're going to buy;
# when it goes down we're going to sell.
# Hopefully we'll ride the waves.
from collections import deque
import math
import talib
atr = ta.ATR(timeperiod=20) # used to calculate 20-day ATR
# To run an algorithm in Quantopian, you need two functions:
# initialize and handle_data.
def initialize(context):
# The initialize function sets any data or variables that
# you'll use in your algorithm.
# For instance, you'll want to define the security
# (or securities) you want to backtest.
# You'll also want to define any parameters or values
# you're going to use later.
# It's only called once at the beginning of your algorithm.
# In our example, we're looking at Apple.
# If you re-type this line you'll see
# the auto-complete that is available for security.
set_symbol_lookup_date('2014-01-04')
context.securities = symbols('AAPL', 'AMZN', 'YHOO',
'JNJ', 'EMC', 'GE', 'ORCL',
'IBM', 'MSFT', 'EBAY', 'FB', 'NVDA',
'AKAM', 'TWTR', 'SPLK', 'WDAY',
'CRM', 'TSLA', 'VRNT', 'SCOR',
'PCG', 'V', 'PFE', 'TIF',
'TGT', 'WMT')
#set_benchmark(symbol('WMT'))
#context.securities = symbols('WMT')
# define dicts for deques to contain past prices
context.past_highs = dict()
context.past_lows = dict()
context.stop_price = dict()
context.first = True
set_slippage(slippage.FixedSlippage(spread=0.00))
# The handle_data function is where the real work is done.
# This function is run either every minute
# (in live trading and minute backtesting mode)
# or every day (in daily backtesting mode).
def handle_data(context, data):
# We've built a handful of useful data transforms for you to use,
# such as moving average.
if context.first:
cash = context.portfolio.cash
cash_per_security = cash / len(context.securities)
context.held_shares = dict()
for security in data:
num_shares = int(cash_per_security / data[security].price)
# order(security, num_shares)
log.info("Buy-n-hold {} shares of {}".format(num_shares, security.symbol))
cash -= data[security].price * num_shares
context.held_shares[security] = num_shares
context.virtually_left_cash = cash
context.first = False
# To make market decisions, we're calculating the stock's
# moving average for the last 5 days and its current price.
#average_price = data[context.security].mavg(5)
#current_price = data[context.security].price
# Another powerful built-in feature of the Quantopian backtester is the
# portfolio object. The portfolio object tracks your positions, cash,
# cost basis of specific holdings, and more. In this line, we calculate
# the current amount of cash in our portfolio.
highs = history(21, '1d', 'high')
lows = history(21, '1d', 'low')
closes = history(21, '1d', 'close_price')
if len(closes) < 21:
return
# for each security in the list
for security in context.securities:
# count how many shares we have in open orders and own
shares = 0
for o in get_open_orders(security):
shares += o.amount
shares += context.portfolio.positions[security].amount
# determine account size
current_value = context.portfolio.cash + context.portfolio.positions_value
if current_value < context.portfolio.starting_cash:
account_size = -context.portfolio.starting_cash + 2*current_value
else:
account_size = current_value
price = data[security].price
ATR = talib.ATR(highs[security], lows[security], closes[security])
# get 20 day ATR
# ATR returns an array, you want the last value
N = ATR[-1]
# 10 day low for exit
#l_10 = min(list(context.past_lows[security])[10:])
l_10 = talib.MIN(lows[security][0:-1], timeperiod=10)[-1]
# 20-day high?
# h_20 = max(context.past_highs[security])
h_20 = talib.MAX(highs[security][0:-1], timeperiod=20)[-1]
#dt = data[security].datetime
#if dt.year == 2014 and dt.month == 2 :
# log.info('20-day high/price = {}/{}'.format(h_20, price))
if shares > 0:
# look for exit
if context.stop_price[security] > price:
# stop loss
order(security, -shares)
log.info('stop {} shares of {}: entry/current/stop = {}/{}/{}'.format(shares, security.symbol, context.portfolio.positions[security].cost_basis, price, context.stop_price[security]))
elif price < l_10:
order(security, -shares)
log.info('exit {} shares of {}: entry/current/stop/l_10 = {}/{}/{}/{}'.format(shares, security.symbol, context.portfolio.positions[security].cost_basis, price, context.stop_price[security], l_10))
# compute how many units to buy or sell
trade_amt = math.floor(account_size*.01/N)
goal_shares = shares
if price > h_20:
# long
goal_shares = trade_amt
# goal_shares = shares + (amount to buy or sell)
amt_to_buy = goal_shares - shares
if amt_to_buy > 0:
stop_price = data[security].price - 2*N
log.info("buying {} shares of {}: price/stop = {}/{}".format(amt_to_buy, security.symbol, price, stop_price))
order(security, amt_to_buy)
context.stop_price[security] = stop_price
# keep deques updated
#context.past_highs[security].append(data[security].high)
#context.past_lows[security].append(data[security].low)
if len(context.securities) == 1:
record(price=data[security].price, l_10=l_10, h_20=h_20)
else:
position_value = 0
for sid, num in context.held_shares.items():
position_value += data[sid].price * num
record(balance=context.portfolio.portfolio_value,
buy_n_hold=context.virtually_left_cash + position_value)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment