Shorting based on Sentiment Analysis signals - Python for Finance 11

Algorithmic trading with Python Tutorial




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.

The next tutorial:





  • Programming for Finance with Python, Zipline and Quantopian
  • Programming for Finance Part 2 - Creating an automated trading strategy
  • Programming for Finance Part 3 - Back Testing Strategy
  • Accessing Fundamental company Data - Programming for Finance with Python - Part 4
  • Back-testing our strategy - Programming for Finance with Python - part 5
  • Strategy Sell Logic with Schedule Function with Quantopian - Python for Finance 6
  • Stop-Loss in our trading strategy - Python for Finance with Quantopian and Zipline 7
  • Achieving Targets - Python for Finance with Zipline and Quantopian 8
  • Quantopian Fetcher - Python for Finance with Zipline and Quantopian 9
  • Trading Logic with Sentiment Analysis Signals - Python for Finance 10
  • Shorting based on Sentiment Analysis signals - Python for Finance 11
  • Paper Trading a Strategy on Quantopian - Python for Finance 12
  • Understanding Hedgefund and other financial Objectives - Python for Finance 13
  • Building Machine Learning Framework - Python for Finance 14
  • Creating Machine Learning Classifier Feature Sets - Python for Finance 15
  • Creating our Machine Learning Classifiers - Python for Finance 16
  • Testing our Machine Learning Strategy - Python for Finance 17
  • Understanding Leverage - Python for Finance 18
  • Quantopian Pipeline Tutorial Introduction
  • Simple Quantopian Pipeline Strategy