In this Finance with Python tutorial, we're going to continue building our strategy, this time including shorting.
To do this, we're going to add mainly the following block of code:
if context.shorting: ma1 = data[s].mavg(100) ma2 = data[s].mavg(300) if (sentiment <= -3) and (current_position) == 0: if ma2 > ma1: if cash > context.investment_size: order_value(s, -context.investment_size) context.shorts.append(s) elif (sentiment >= -1) and (current_position > 0) and s in context.shorts: order_target(s, 0) context.shorts.remove(s)
In order to short, we're going to require one more check, which will be whether or not the 100 moving average is below the 300. This way we wont find ourselves in a never-ending short that blows our account up, and we're requiring some agreement from the market before we actually execute a short. We will not require any agreement to exit the short position.
We're also going to keep track of our shorts.
The full code for this strategy:
# Put any initialization logic here. The context object will be passed to # the other methods in your algorithm. def preview(df): log.info(df.head()) return df def initialize(context): context.investment_size = (context.portfolio.cash / 10.0) context.stop_loss_pct = 0.995 context.shorting = True context.shorts = [] set_symbol_lookup_date('2012-10-01') fetch_csv('http://sentdex.com/api/finance/sentiment-signals/sample/', pre_func = preview) context.stocks = symbols('AAPL', 'MCD', 'FB', 'GME', 'INTC', 'SBUX', 'T', 'MGM', 'SHLD', 'NKE', 'NFLX', 'PFE', 'GS', 'TGT', 'NOK', 'SNE', 'TXN', 'JNJ', 'KO', 'VZ', 'XOM', 'WMT', 'MCO', 'TWTR', 'URBN', 'MCP', 'MSFT', 'HD', 'KSS', 'AMZN', 'S', 'BA', 'F', 'JPM', 'QCOM', 'TSLA', 'YHOO', 'BBRY', 'GM', 'IBM', 'C', 'ZNGA', 'BAC', 'DIS', 'SCHW', 'UA', 'CSCO', 'ORCL', 'SYMC', 'WFC', 'TM', 'EBAY', 'SCHL', 'MS', 'NDAQ', 'TIF', 'AIG', 'DAL', 'JCP', 'MRK', 'CA', 'SIRI', 'AMD', 'CVX', 'FSLR', 'LMT', 'P', 'CBS', 'TWX', 'PEP', 'LNKD', 'CMG', 'NVDA', 'BBY', 'TWC', 'M', 'RHT', 'ACN', 'CRM', 'PETS', 'CELG', 'BLK', 'GD', 'DOW', 'YUM', 'GE', 'MA', 'DTV', 'DDD', 'CAT', 'FDX', 'GRPN', 'ACE', 'BK', 'GILD', 'V', 'DUK', 'FFIV', 'WFM', 'CVS', 'UNH', 'LUV', 'CBG', 'AFL', 'CHK', 'BRCM', 'HPQ', 'LULU', 'ATVI', 'RTN', 'EMC', 'NOC', 'MAR', 'X', 'BMY', 'LOW', 'COST', 'HON', 'SPLS', 'BKS', 'AA', 'AXP', 'AMGN', 'GPS', 'MDT', 'LLY', 'CME', 'MON', 'WWWW', 'MU', 'DG', 'TRIP', 'HAL', 'COH', 'WYNN', 'PCLN', 'HTZ', 'CLF', 'DD', 'ACI', 'FCX', 'AON', 'GMCR', 'CSX', 'ADBE', 'PRU', 'PG', 'MYL', 'STT', 'PPG', 'EXPE', 'KORS', 'JNPR', 'UTX', 'HOT', 'SNDK', 'CCL', 'DRI', 'BIIB', 'MHFI', 'BBT', 'APA', 'A', 'TDC', 'ANF', 'MTB', 'PPL', 'ABT', 'GNW', 'KMI', 'MET', 'FE', 'DVA', 'ETFC', 'GLW', 'NRG', 'INTU', 'KR', 'ARNA', 'VALE', 'MSI', 'EOG', 'AET', 'MAT', 'HST', 'COP', 'MO', 'IVZ', 'HUM', 'NUE', 'CI') # Will be called on every trade event for the securities you specify. def handle_data(context, data): cash = context.portfolio.cash try: for s in data: if 'sentiment_signal' in data[s]: sentiment = data[s]['sentiment_signal'] current_position = context.portfolio.positions[s].amount current_price = data[s].price # Begin Long Logic if (sentiment > 5) and (current_position == 0): if cash > context.investment_size: order_value(s, context.investment_size, style=StopOrder(current_price * context.stop_loss_pct)) cash -= context.investment_size elif (sentiment <= -1) and (current_position > 0): order_target(s,0) # Begin Shorting Logic if context.shorting: ma1 = data[s].mavg(100) ma2 = data[s].mavg(300) if (sentiment <= -3) and (current_position) == 0: if ma2 > ma1: if cash > context.investment_size: order_value(s, -context.investment_size) context.shorts.append(s) elif (sentiment >= -1) and (current_position > 0) and s in context.shorts: order_target(s, 0) context.shorts.remove(s) except Exception as e: print(str(e))
Results:
We do considerably better this time, though we do wind up taking on some leverage here. That said, our Alpha is decent, Beta is within competition range, the Sharpe Ratio is approaching excellence, and max drawdown is very good. All this alongside the fact that we're hedged with this strategy puts us in a great place.
All of that said, we're now going to move away from this strategy in the interest of learning about more methods for back-testing without needing to use a paid API. Next up, we're going to cover paper-trading, which is a way to "forward test" a strategy. This means we'll trade the strategy against market prices in real time moving forward. This helps us eliminate hindsight bias.