Strategy Sell Logic with Schedule Function with Quantopian - Python for Finance 6

Algorithmic trading with Python Tutorial




In our last finance with Python tutorial, we created and tested our basic strategy based on fundamental company data. The only problem is that we currently only buy, but never exit companies. We need to build this in!

Revisiting the concept of our strategy, the plan is:

Buy up to 10 companies that have a PE ratio less than 11 (and PB ratio less than 2). Hold these, until the PE ratio gets above 14, or until the PB ratio gets above 2.

The way we can handle for this is to check to see if the companies we have positions with are also in our "universe," meaning that they are under 14 PE and under 2 PB. If not, then we want to go ahead and sell these companies off.

To do this, we're going to bring in a new functionality with Quantopian, called schedule_function, which does exactly what it sounds like it does: Lets us schedule a function!

The way it works is you slap that method in your initialize method, giving the name of the function you wish to schedule, giving it a date_rule and a time_rule. The date rule will be how frequently you want it to run. You have choices like daily, weekly, monthly, and so on. The time rule lets you govern at what time of the day you want this scheduled function to run, things like before market open, at market open, at market close, and so on.

For example, here's our new initialize method:

def initialize(context):
    context.limit = 10
    
    schedule_function(rebalance,
                     date_rule = date_rules.every_day(),
                     time_rule = time_rules.market_open())

In this case, we call schedule_function to run a function called rebalance, which will run every day, at market open.

Great, time to make our rebalance function!

def rebalance(context, data):
    for stock in context.portfolio.positions:
        if stock not in context.fundamentals and stock in data:
            order_target_percent(stock, 0)

Here, we pass both context and data. Remember which does what? Context tracks your trading algorithm's state. Data tracks your universe.

In our rebalance function, what we do is iterate through all of the stocks that are in our portfolio currently. Then, we just ask whether or not those stocks are in context.fundamentals. If the stock isn't in our context.fundamentals (which means it is one of the top 10 companies by market cap with below 14 PE and below 2 PB), yet we have this company in our portfolio, we want to send it to the chopping block! If this is the case, we sell the company. To do this, we use a new selling method, order_target_percent. With this method, we can set a "target" percentage of our portfolio to be allocated to the asset we pass. Careful, you can easily leverage yourself with this method. If you buy 6 companies with a target percent of 20% of your portfolio, you'll become over-invested, or leveraged.

With these changes, the full code:

def initialize(context):
    context.limit = 10
    
    schedule_function(rebalance,
                     date_rule = date_rules.every_day(),
                     time_rule = time_rules.market_open())
    
    
def rebalance(context, data):
    for stock in context.portfolio.positions:
        if stock not in context.fundamentals and stock in data:
            order_target_percent(stock, 0)
        

# Will be called on every trade event for the securities you specify. 
def before_trading_start(context):
    context.fundamentals = get_fundamentals(
        query(
            fundamentals.valuation_ratios.pb_ratio,
            fundamentals.valuation_ratios.pe_ratio,
        )
        .filter(
            fundamentals.valuation_ratios.pe_ratio < 14
        )
        .filter(
            fundamentals.valuation_ratios.pb_ratio < 2
        )
        .order_by(
            fundamentals.valuation.market_cap.desc()
        )
        .limit(context.limit)
    )
    

    
    update_universe(context.fundamentals.columns.values)
    


def handle_data(context, data):
    cash = context.portfolio.cash
    current_positions = context.portfolio.positions
    
    for stock in data:
        current_position = context.portfolio.positions[stock].amount
        stock_price = data[stock].price
        plausible_investment = cash / context.limit
     
        share_amount = int(plausible_investment / stock_price)
        
        try:
            if stock_price < plausible_investment:
                if current_position == 0:
                    if context.fundamentals[stock]['pe_ratio'] < 11:
                        order(stock, share_amount)
                    
                
            
        except Exception as e:
            print(str(e))

The results, depending on the dates you use:

Still nothing to write home about or apply to Goldman Sachs with, but better than when we didn't sell at all (previous returns for the same date range were -1.3%)

Now, I know it might be hard to accept, but it might be the case that sometimes we're making mistakes when we buy with our logic. To compensate for this, we can try to use stop-loss in our strategy. Stop-loss is a method used by traders to "cut their losses" at a certain point. Say you bought a company for $100, expecting it to go to $125. Instead, it just keeps dropping. With stop-loss, you can set a limit, say $89. If price falls below $89, then you want to just cut your losses. That's what we'll be covering next.

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