Back to Community
Sentiment Analysis Algorithm

Hi! My name is Chris and I am part of a company called Senvision.

We aim to give millennials the tools we never had to invest with. This is the algorithm we have developed to run in the background so that our customers can leave their money alone. It uses sentiment analysis with twitter to predict whether a company will rise or fall the next day. Currently, we invest in 8 companies: Google, Apple, Boeing, Procter & Gamble, Merck, Walmart, Intel, and JP Morgan Chase. All the analysis is done on a server on our end, and the results are uploaded to web published drive files. We are releasing this for free to be able to tell our first customers that not only have we, the founders, made money with our algorithm, other people have too. This algorithm takes advantage of Robinhood instant, and its promise of free trades and instant reimbursement of money, so you must have that to use this. To use it, click Live trade algorithm and connect with your Robinhood account. We would love for you to try it out and tell us how it goes in the comments!

IMPORTANT NOTE
To use the algorithm, you must uncomment the 3rd instance of fetch_csv and comment out the 2nd one. The instructions can be found in the code.

P.S. We are not entering this in the Quantopian contest because it uses fetch_csv, and the contest does not allow that.

Chris

Clone Algorithm
204
Loading...
Total Returns
--
Alpha
--
Beta
--
Sharpe
--
Sortino
--
Max Drawdown
--
Benchmark Returns
--
Volatility
--
Returns 1 Month 3 Month 6 Month 12 Month
Alpha 1 Month 3 Month 6 Month 12 Month
Beta 1 Month 3 Month 6 Month 12 Month
Sharpe 1 Month 3 Month 6 Month 12 Month
Sortino 1 Month 3 Month 6 Month 12 Month
Volatility 1 Month 3 Month 6 Month 12 Month
Max Drawdown 1 Month 3 Month 6 Month 12 Month
# if you want to backtest, make sure to (un)comment out the right
# fetch_csv, change lowercase 'pred' to 'Pred' or vice versa

def preview(df):
    log.info(df.head())
    return df

# The initialize function is the place to set your tradable
# universe and define any parameters. 
def initialize(context):
    # Robinhood only allows long positions, use this trading
    # guard in case
    set_long_only()
    # Since we are trading with Robinhood we can set this to $0!
    set_commission(commission.PerTrade(cost=0))
    set_symbol_lookup_date('2017-08-09')
    ## Initialize list of securities we want to trade
    context.security_list = symbols('AAPL', 'BA', 'MRK', 'WMT', 'INTC', 'PG', 'JPM')
    #context.security_list = symbols('INTC', 'ETE', 'ETFC', 'NDAQ')
    ## Trailing stop loss
    context.stop_loss_pct = .995
    ## Also not sure if this is needed yet
    set_slippage(slippage.FixedSlippage(spread=0.1))
    # We will weight each asset equally and leave a 5% cash
    # reserve. - actually this is sort of good idea
    # but it's not needed rn?
    context.weight = 0.95 / len(context.security_list)
    # test live trading - the first csv is w 4 small companies,
    #the second csv is our algorithm's predictions
    
    #fetch_csv("https://docs.google.com/spreadsheets/d/11rYrFpT6PpwHqcB6nJc6ehst0KV5gXJ6jPY5kpa3W4c/pub?gid=0&single=true&output=csv", date_column = 'date', date_format = '%y-%m-%d')
    
    
    
    #############################################################################
    ##################Uncomment below command to use live trading################
    #############################################################################
    #fetch_csv("https://docs.google.com/spreadsheets/d/e/2PACX-1vR4zi6MD7t1kLXBqUmpjggyjSQDIUITZK0MGgNyAKEBRr7ue4LtPdoV0SAs6wT6-kIQpRJCp3urrImT/pub?gid=1607988061&single=true&output=csv", date_column = 'date', date_format = '%y-%m-%d')

    
    
    # predictions for august 2016 - march 2017 to backtest on
 	#############################################################################
    ###################Comment out below line to use live trading################
    #############################################################################
    fetch_csv("https://docs.google.com/spreadsheets/d/1oTwUIqXWqRlOJUWszikMNd8IYlnbMQ2nGtUYlQrEwWw/pub?gid=282201860&single=true&output=csv", date_column = 'date', date_format = '%y-%m-%d')
    
    
    
    context.first_trade = False
    
    #schedule_function(first_trade, date_rules.every_day(),
    #                  time_rules.market_open(minutes=5))
    
    schedule_function(myfunc, date_rules.every_day(), 
        time_rules.market_open(hours=0, minutes=1)) 
    


# Will be called on every trade event for the securities you specify. 
def myfunc(context, data):
    # calculate how much is currently invested in the 
    # selected POSITIVE companies with this algorithm, 
    # to determine total portfolio + cash value
    
    if (context.first_trade == False):
        
        cash = context.portfolio.cash * 0.95
        numplus = 0
        companies_up = []
        for s in context.security_list:
            sentiment = data.current(s, 'pred')
            current_price = data.current(s, 'price')
            current_position = context.portfolio.positions[s].amount
            current_value = current_position * current_price
        
            if (sentiment == "+"):
                cash += current_value
                numplus += 1
                companies_up.append(s)
            
        print("number of positive companies today:", numplus)

        try:
        # sell all companies with negative sentiment values that we are currently invested in
            for s in context.security_list:
                sentiment = data.current(s, 'pred')
                #conf_interval = data.current(s, 'Conf')
                current_price = data.current(s, 'price')
                current_position = context.portfolio.positions[s].amount
                print s," ",data.current(s,'price')
                #current_price = data.current(s, 'price')
                current_value = current_position * current_price
                if (sentiment == '-') and (current_position > 0):
                    #print('selling...' + str(s))
                    cash += current_value
                    order_target(s,0)

            # how much $ we'll have to invest, depends on how much
            # we've gained from selling in the previous part
            print("amount of cash after selling:", cash)
            context.investment_size = float(cash / numplus)
            print("investment size", context.investment_size)
        
            for s in companies_up:
                current_price = data.current(s, 'price')
                current_position = context.portfolio.positions[s].amount
                current_value = current_price * current_position
                if (current_value > context.investment_size):
                    order_target_value(s, context.investment_size)#, style=StopOrder(current_price * context.stop_loss_pct))
                
            for s in companies_up:
                current_price = data.current(s, 'price')
                current_position = context.portfolio.positions[s].amount
                current_value = current_price * current_position
                if (current_value <= context.investment_size):
                    order_target_value(s, context.investment_size)#, style=StopOrder(current_price * context.stop_loss_pct))
            
        
        #for s in context.security_list:
        #    sentiment = data.current(s, 'pred')
        #    current_price = data.current(s, 'price')
        #    #conf_interval = data.current(s, 'Conf')
        #    # number of shares you have of s security
        #    current_position = context.portfolio.positions[s].amount
        #    # current value in security is # stocks * its current price
        #    # bc you can sell that ish for that value.
        #    if (sentiment == "'+" and numplus > 0):
        #        order_target(s, context.investment_size/current_price, style=StopOrder(current_price * context.stop_loss_pct))
                #order_target_value(s, context.investment_size, style=StopOrder(current_price * context.stop_loss_pct))
        except Exception as e:
            print(str(e))

        
# first day's trades!!!
def first_trade(context, data):
    if context.first_trade:
        cash = context.portfolio.cash
        context.investment_size = 0
        companies_up = []
        numplus = 0
        for s in context.security_list:
            sentiment = data.current(s, 'pred')
            current_price = data.current(s, 'price')
            current_position = context.portfolio.positions[s].amount
            current_value = current_position * current_price
            if (sentiment == "+"):
                cash += current_value
                numplus += 1 
                companies_up.append(s)
        if (numplus > 0):
            context.investment_size = float(cash/numplus)
            
        for s in companies_up:
            order_target_value(s, context.investment_size)
        
        context.first_trade = False

def do_unsettled_funds_exist(context):
    """
    For Robinhood users. In order to prevent you from attempting
    to trade on unsettled cash (settlement dates are T+3) from
    sale of proceeds. You can use this snippet of code which
    checks for whether or not you currently have unsettled funds
    """
    if context.portfolio.cash != context.account.settled_cash:
        return True
    # we will require our users to get Robinhood instant, so this really
    # shouldn't be necessary. come back to it if it is, though!

# The handle_data function is run every bar. In this case we'll 
# use this function to plot our leverage over time.
def handle_data(context, data):
    record(leverage=context.account.leverage)
There was a runtime error.
4 responses

Hi, Chris -- great, thanks for sharing this!

How long have you been live-trading it? I'm curious how much out-of-sample data you have collected to confirm its efficacy.

Hi Chris. With a fixed asset listy you limit future development. Wouldnt it be better to make the asset list dynamic so you can add signals.

Secondly, I tried to open yiour live trade file and it's not accessible

Hi Peter Bakker,

Thank you so much for your feedback! For your first question, we would like to have more companies in the list, but we search twitter for tweets relevant to the company and train a model with that data, so we are limited by the twitter API, which can get very expensive very quickly. Thus we have limited the companies we find sentiment signals for to 8 companies. We plan to add signals in the future, but that would be after this free version.

Secondly, the link for the live trade file worked for me from a separate account. Here is the link we had: https://docs.google.com/spreadsheets/d/e/2PACX-1vR4zi6MD7t1kLXBqUmpjggyjSQDIUITZK0MGgNyAKEBRr7ue4LtPdoV0SAs6wT6-kIQpRJCp3urrImT/pub?gid=1607988061&single=true&output=csv. It should download a csv to your computer. What is the error you're getting?

Chris

Hi Viridian Hawk,

Thank you for your response. We used a version of this algorithm with News data instead of twitter for 4 months from April 2nd to June 27th, and it made 5.5% returns on 2,500, while the SPY made 2.4%, and the average returns of the 7 companies over that time period was 2.7%. (We did not have an algorithmic way of actually executing the trades so for those months I had to do the trades myself on Robinhood using our output predictions). We did not include Google in our investments because we did not have enough money to make a $1,000 position only 1/8th of our portfolio worth, which is why we only included 7 companies in our average. We had to stop using it for a bit because the news API we were using cut our rates by 7x so we were not able to get enough data a day to make predictions. We have started using this algorithm again using the twitter data we were collecting since Sep 2016.

I hope this clarifies things, let me know if you have anymore questions
Chris