Trading Logic with Sentiment Analysis Signals - Python for Finance 10

Algorithmic trading with Python and Sentiment Analysis Tutorial




To recap, we're interested in using sentiment analysis from Sentdex to include into our algorithmic trading strategy.

Since Quantopian limits the amount of companies in our universe, first we need to get a list of ~200 companies that we want to trade. To do this, we're going to reference the top 200 companies in terms of sentiment volume that is collected. To get that, we can reference the Sentdex sentiment analysis API again, heading to: Top 200 Companies by sentiment volume

This list allows us to copy and paste it into a parameter to cycle through within our script, called context.stocks:

def initialize(context):
    context.investment_size = (context.portfolio.cash / 10.0)
    context.stop_loss_pct = 0.995
    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')

Next up, we need to write the trading logic that will trade based on sentiment signals:

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
                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)
    except Exception as e:
        print(str(e))

In here, we cycle through each of the companies in our data, which is each of the 200 companies we specified to context.stocks. From here, we want to see if "sentiment_signal" is contained for that stock's data. What is happening here? The way the fetch_csv method works, is it will grab the CSV, which is organized by date. The handle_data method runs through day by day, so what is happening behind the scenes is the handle_data method is looking at all returns for that specific date. Then, we iterate through all of our plausible stocks from context.stocks, asking if there is a sentiment_signal, today, for each.

If there is a sentiment analysis signal for that company for that day, then we might be interested in investing, so the next step we take is to reference our current position in that company, to see if we're already invested. Next, we grab the current price of that company.

Next, we're ready to consider our strategy. To keep things simple, we're going to look for stocks with a sentiment signal rating of 6 for buying into them, and then look for stocks with a sentiment signal of -3 to short them. You can feel free to play with these values, but this is what we'll be using for now. So, we'll ask if either of these are the case, and, if so, we're going to place a buy.

Ignoring shorting for now, we need to consider how we will actually exit a company. We will incorporate a stop-loss, but this is obviously not enough. So, what we're going to do is require that sentiment is less than or equal to -1, or basically meaning less than 0. If that is the case, and we more than 0 positions (1 or more), then we want to sell all of our shares.

Running the full code, which should be:

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
    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
                
                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)

    except Exception as e:
        print(str(e))

The results, choosing Oct 20 2012 to June 15 2015:

Very exciting results for me, to say the least! Beta is too high for Quantopian, but the Sharpe Ratio is on a great track. One way we can get Beta down as shown before? Shorting! Right now, we're only willing to go long, so it is only naturual that the Beta is close to a perfect 1.

In the next tutorial, we'll include shorting, as well as a bit of a safeguard for shorting.

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