# This is the standard Quantopian function that initializes your data and # variables. In it, we define how large of a 'bet' we're making (in dollars) and what # stock we're working with. def initialize(context): # we will be trading in AMZN and WMT shares context.stocks = symbols('AMZN', 'WMT') context.bet_amount = 100000 context.long = 0 # This is the standard Quantopian event handling function. This function is # run once for each bar of data. In this example, it the min and max # prices for the trailing window. If the price exceeds the recent high, it # goes short; if the price dips below the recent low, it goes long. The algo # is a contrarian/mean reversion bet. def handle_data(context, data): # Until our batch transform's datapanel is full, it will return None. Once # the datapanel is full, then we have a max and min to work with. rval = minmax(data) if rval is None: return maximums, minimums = rval for stock in context.stocks: cur_max = maximums[stock] cur_min = minimums[stock] cur_price = data[stock].price cur_position = context.portfolio.positions[stock] order_direction = calculate_direction(stock, cur_min, cur_max, cur_price, cur_position) order_amount = calculate_order_amount(context, stock, order_direction, cur_price) # Optional: uncomment the log line below if you're looking for more detail about what's # going on. It will log all the information that is a 'moving part' of this # algorithm. Note: if you're doing a full backtest it's a lot of log lines! logmsg = '\n{s}: max {m} min {i} price {p} position amount {l}\nordering {n} shares' log.info(logmsg.format( s=stock, m=cur_max, i=cur_min, p=cur_price, l=cur_position.amount, n=order_amount )) order(stock, order_amount) # Here we do our test to see if we should buy or sell or do nothing. This is # the main part of the algorithm. Once we establish a position (long or short) # we use the context.long variable to remember which we took. def calculate_direction(stock, cur_min, cur_max, cur_price, cur_position): if cur_max is not None and cur_position.amount <= 0 and cur_price >= cur_max: return -1 elif cur_min is not None and cur_position.amount >= 0 and cur_price <= cur_min: return 1 return 0 # This method is purely for order management. It calculates and returns an # order amount to place binary bets. # If signal_val is -1, get to a short position of -1 * context.bet_size # If signal_val is 1, get to a long position of context.bet_size def calculate_order_amount(context, stock, signal_val, cur_price): current_amount = context.portfolio.positions[stock].amount abs_order_amount = int(context.bet_amount / cur_price) if signal_val == -1: return (-1 * abs_order_amount) - current_amount elif signal_val == 1: return abs_order_amount - current_amount else: return 0 # This is our batch transform decorator/declaration. We set the # refresh_period and length of the window. In this case, once per day we're loading # the last 10 trading days and evaluating them. @batch_transform(refresh_period=1, window_length=10) def minmax(datapanel): # We are looking for the min and the max price to return. Just because it's interesting # we also are logging the current price. prices_df = datapanel['price'] min_price = prices_df.min() max_price = prices_df.max() if min_price is not None and max_price is not None: return (max_price, min_price) else: return None
2015年5月22日 星期五
Batch Transform
訂閱:
張貼留言 (Atom)
沒有留言:
張貼留言