Back to Community
Stop Loss Error

Hey all,

Sorry total noob! If there is not an easy fix for this problem that is fine, just looking for explanation as to why I keep getting an error for context.init_stop_price on line 140 -- specifically:
price * context.initial_short_stop

Thanks!

Clone Algorithm
5
Loading...
Backtest from to with initial capital
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
from quantopian.algorithm import attach_pipeline, pipeline_output
from quantopian.pipeline import Pipeline
from quantopian.pipeline.data.builtin import USEquityPricing
from quantopian.pipeline.factors import Returns, SimpleMovingAverage, CustomFactor, AverageDollarVolume
from quantopian.pipeline.data import morningstar
from collections import defaultdict
import numpy as np
from pykalman import KalmanFilter
import pandas as pd

class Volatility(CustomFactor): #meh, we'll see
    inputs = [USEquityPricing.close]
    window_length=252
    
    def compute(self, today, assets, out, close):
        close_df = pd.DataFrame(data=close, columns=assets) 
        # Since we are going to rank largest is best we need to negate the sdev.
        out[:] = -np.log(close_df).diff().std()

class MarketCap(CustomFactor): #small cap -- masked w/ sma of price and volume
    inputs = [morningstar.valuation.market_cap]
    window_length=1
    
    def compute(self, today, assets, out, market_cap):
        out[:] = -market_cap[-1] #invert b/c prefer smaller

class Dividend(CustomFactor):
    inputs = [morningstar.valuation_ratios.forward_dividend_yield]
    window_length=1
    
    def compute(self, today, assets, out, div_yield):
        out[:] = div_yield[-1]

class Momentum(CustomFactor):
    inputs = [USEquityPricing.close]
    window_length=252
    
    def compute(self, today, assets, out, close):
        out[:] = ((close[-50] - close[-200]) / close[-200]) / np.nanstd(close)
        
        
class Value(CustomFactor):
    inputs = [morningstar.valuation_ratios.fcf_yield,
              morningstar.valuation_ratios.earning_yield]
    window_length = 1
    
    def compute(self, today, assets, out, fcf_yield, earning_yield):
        value_df = pd.DataFrame(index=assets)
        value_df['fcf yield'] = fcf_yield[-1]
        value_df['earning yield'] = earning_yield[-1]
        out[:] = value_df.rank().mean(axis=1)

class Quality(CustomFactor):
    inputs = [morningstar.operation_ratios.total_debt_equity_ratio, #lower = better
              morningstar.operation_ratios.roe,
              morningstar.operation_ratios.ebitda_margin,
              morningstar.operation_ratios.net_income_growth,
              morningstar.balance_sheet.current_accrued_expenses] #lower = better
    window_length=1
    
    def compute(self, today, assets, out, debt_to_equity, roe, ebitda, net_income, accruals):
        quality_df = pd.DataFrame(index=assets)
        quality_df['debt to equity'] = -debt_to_equity[-1]
        quality_df['roe'] = roe[-1]
        quality_df['ebitda'] = ebitda[-1]
        quality_df['net income growth'] = net_income[-1]
        quality_df['accruals'] = -accruals[-1]
        out[:] = quality_df.rank().mean(axis=1)

def initialize(context):
    
    pipe = Pipeline()
    attach_pipeline(pipe, 'factors')
    
    context.long_leverage = .5
    context.short_leverage = -.5
    context.trail_long_stop = .925
    context.initial_long_stop = .95
    context.trail_short_stop = 1.075
    context.initial_short_stop = 1.05
    context.default_stop = defaultdict(lambda:0)
    context.returns_lookback = 5
    
    
    dollar_volume = AverageDollarVolume(window_length=90)
    volume_filter = dollar_volume.percentile_between(50,100)
    

    div_yield = Dividend(mask=volume_filter)
    screen = div_yield < .025
    
    volatility = Volatility(mask=volume_filter)
    market_cap = MarketCap(mask=volume_filter)
    value = Value(mask=volume_filter)
    momentum = Momentum(mask=volume_filter)
    quality = Quality(mask=volume_filter)
   
    pipe.add(volatility, 'volatility')
    pipe.add(market_cap, 'market cap')
    pipe.add(value, 'value')
    pipe.add(momentum, 'momentum')
    pipe.add(quality, 'quality')
    
    
    
    
    sma200 = SimpleMovingAverage(inputs=[USEquityPricing.close],
                                 window_length=100,
                                 mask=screen)
    pipe.set_screen(sma200 > 5)

    schedule_function(record_vars, date_rules.every_day(),
                      time_rules.market_close(minutes=1))

    schedule_function(rebalance, date_rules.week_start(),
                      time_rules.market_open(minutes=45))
    
    schedule_function(cancel_open_orders, date_rules.every_day(),
                      time_rules.market_close(minutes=45))

def before_trading_start(context, data):
    
    context.results = pipeline_output('factors').dropna()
    ranks = context.results.rank().mean(axis=1).sort_values()

    #THIS IS SO KEY -- VERY EASY!!!!
    lower, upper = ranks.quantile([.1, .9])
    context.longs = ranks[ranks >= upper]
    context.shorts = ranks[ranks <= lower]

### THIS IS WHERE I CHANGED SHIT ###
def rebalance(context, data):
    
    for stock in context.shorts.index:
        if get_open_orders(stock):
            continue
        if data.can_trade(stock):
            price = data.current(stock, 'price')
            context.init_stop_price[stock] = max(context.default_stop[stock],
                                                 price * context.initial_short_stop)
            
            order_target_percent(stock, context.short_leverage / len(context.shorts))
            
        
    for stock in context.longs.index:
        if get_open_orders(stock):
            continue
        if data.can_trade(stock):
            price = data.current(stock, 'price')
            context.init_stop_price[stock] = max(context.default_stop[stock],
                                                 price * context.initial_long_stop)
           
            order_target_percent(stock, context.long_leverage / len(context.longs))
            
            
    for stock in context.portfolio.positions:
        if get_open_orders(stock):
            continue
        if data.can_trade(stock):
            if stock not in (context.longs.index | context.shorts.index):
                order_target_percent(stock, 0)


def cancel_open_orders(context, data):
    for stock in get_open_orders():
        for order in get_open_orders(stock):
            cancel_order(order)

    
def handle_data(context, data): 
    
    set_trailing_stop(context, data)
    for stock in context.portfolio.positions:
        if data.current(stock, 'price') < context.stop_price[stock]:
            order_target(stock, 0)
            context.stop_price[stock] = 0

def record_vars(context, data):
    """
    This function is called at the end of each day and plots certain variables.
    """

    # Check how many long and short positions we have.
    longs = shorts = 0
    for position in context.portfolio.positions.itervalues():
        if position.amount > 0:
            longs += 1
        if position.amount < 0:
            shorts += 1

    record(leverage = context.account.leverage, long_count=longs, short_count=shorts)
        
        

def set_trailing_stop(context, data):
    for stock in context.portfolio.positions:
        
        price = data.current(stock, 'price')
        
        if context.portfolio.positions[stock].amount > 0: #if long position in this stock
            trail_stop_price = context.trail_long_stop * price
            context.stop_price[stock] = max(trail_stop_price, 
                                          context.init_stop_price[stock])
            
            
        if context.portfolio.positions[stock].amount < 0: #if short
            trail_stop_price = context.trail_short_stop * price
            context.stop_price[stock] = max(trail_stop_price, 
                                          context.init_stop_price[stock])
There was a runtime error.
2 responses

You need to tell Python somewhere that "context.init_stop_price" and "context.stop_price" are dictionaries. Putting the following into the "initialize" method is one way.

    context.init_stop_price = {}  
    context.stop_price = {}

Good luck.

Perfect Dan. Thanks!