Created
March 22, 2016 21:23
-
-
Save umitanuki/23b0f2df585fa4e24912 to your computer and use it in GitHub Desktop.
Turtle in quantopian
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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