Back to Community
Why does my algorithm perform worse with StopOrder?

Hello :),

i started learning with Quantopian just a few days ago with the pythonprogramming.net tutorial series. I tried to modify a given algorithm to have stop losses, and now it performs worse then it did without. It isn't a fancy algoritm but what is it what I can not see?

Clone Algorithm
3
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
# Put any initialization logic here.  The context object will be passed to
# the other methods in your algorithm.
def initialize(context):
    context.stocks = symbols(
                           'XLY',   
                           'XLF',   
                           'XLK',  
                           'XLE',   
                           'XLV', 
                           'XLI', 
                           'XLP',  
                           'XLB',  
                           'XLU'
                            )  
def handle_data(context, data):
    for stock in context.stocks:
        ma50 = data[stock].mavg(50)
        ma200 = data[stock].mavg(200)
        
        price = data[stock].price
       
       # stop_price_long = price * 0.95
       # stop_price_short = price * 1.05
        
        if ma50 > ma200:
            order_target_percent(stock, 0.11,style=StopOrder(price - (price*0.005)))
        elif ma200 > ma50:
            order_target_percent(stock, -0.11,style=StopOrder(price + (price*0.005)))
            
            
            
            

            
            
            
            
            
            
            
            
            
            
            
            
There was a runtime error.
6 responses

And here the algorithm without the StopOrder :)

Clone Algorithm
3
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
# Put any initialization logic here.  The context object will be passed to
# the other methods in your algorithm.
def initialize(context):
    context.stocks = symbols(
                           'XLY',   
                           'XLF',   
                           'XLK',  
                           'XLE',   
                           'XLV', 
                           'XLI', 
                           'XLP',  
                           'XLB',  
                           'XLU'
                            )  
def handle_data(context, data):
    for stock in context.stocks:
        ma50 = data[stock].mavg(50)
        ma200 = data[stock].mavg(200)
        
        price = data[stock].price
       
       # stop_price_long = price * 0.95
       # stop_price_short = price * 1.05
        
        if ma50 > ma200:
            order_target_percent(stock, 0.11,)
        elif ma200 > ma50:
            order_target_percent(stock, -0.11,)
There was a runtime error.

That happens - stop orders do not necessarily make things better. It depends what you are looking for.

Also, a lot of the mechanics of a stop order are missing in your example. Here is IB's stop order definition. From that definition,

A Sell Stop order is always placed below the current market price and is typically used to limit a loss or protect a profit on a long stock position. A Buy Stop order is always placed above the current market price. It is typically used to limit a loss or help protect a profit on a short sale.

What this means is that you typically only use stop orders to close positions. You still need to place a limit/market order to open the position. Placing a buy stop with a price below the market price should just cause it to be converted to a market order and executed right away. You will need to make sure you are using the order types correctly before you'll be able to to tell if the stops help.

This backtest implements the stops more like you would in a real situation. For a buy I place a market buy order, and a stop sell order below the current price at the same time, sells are opposite.

Clone Algorithm
10
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
# Put any initialization logic here.  The context object will be passed to
# the other methods in your algorithm.
def initialize(context):
    context.stocks = symbols(
                           'XLY',   
                           'XLF',   
                           'XLK',  
                           'XLE',   
                           'XLV', 
                           'XLI', 
                           'XLP',  
                           'XLB',  
                           'XLU'
                            )  
def handle_data(context, data):
    open_orders = get_open_orders()
    for stock in context.stocks:
        position = context.portfolio.positions[stock].amount
        ma50 = data[stock].mavg(50)
        ma200 = data[stock].mavg(200)
        
        price = data[stock].price
       
       # stop_price_long = price * 0.95
       # stop_price_short = price * 1.05
        
        if ma50 > ma200:
            if position <= 0:
                if stock in open_orders:
                    for oo in open_orders[stock]:
                        cancel_order(oo)
                order_target_percent(stock, 0.11)
                order_target_percent(stock, -0.11, 
                                     style=StopOrder(price - (price*0.005)))
        elif ma200 > ma50:
            if position >= 0:
                if stock in open_orders:
                    for oo in open_orders[stock]:
                        cancel_order(oo)
                order_target_percent(stock, -0.11)
                order_target_percent(stock,  0.11, 
                                         style=StopOrder(price + (price*0.005)))
            
            
            

            
            
            
            
            
            
            
            
            
            
            
            
There was a runtime error.

Thanks for the answer, it helped me a lot :)

No problem, at first glance it seems like the stops do help when they are implemented more correctly. It is usually not trivial to swap around order types, you'll usually need to change the logic around managing the orders as well. Glad my explanation helped.