Back to Community
Controlling Leverage and Not Buying Multiple Times

Hello,

I'm working on an intraday scalper, but my algorithm seems to continuously purchase the same stock even if its already in an open order. My leverage is way out of control because of this.

Can someone take a look at my algorithm and give me a pointer on controlling the orders?

I tried looking at len(get_open_order(stock)) > 0, but that didn't have the desired effect.

Thank you very much!

Clone Algorithm
4
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
"""
Buys top market capitalization stocks that are listed as "oversold" and are exiting their oversold region.  Sell when they enter or exit their oversold region.
"""
from quantopian.algorithm import attach_pipeline, pipeline_output
from quantopian.pipeline import Pipeline
from quantopian.pipeline import CustomFactor
from quantopian.pipeline.data import morningstar
from quantopian.pipeline.data.builtin import USEquityPricing
from quantopian.pipeline.factors import AverageDollarVolume
from quantopian.pipeline.filters import Q1500US
import random
import talib
import numpy as np
import pandas as pd
import math
import datetime
from sqlalchemy import or_

#How many stocks?

numstock = 10

#Bollinger band settings
bbl = 20
mult = 2
#MA settings
mal = 3
bars = bbl + mal

log = 0
takeprofit = 0.10
stoploss = 0.05
usets = 0

class MarketCap(CustomFactor):
    # Pre-declare inputs and window_length  
    inputs = [USEquityPricing.close, morningstar.valuation.shares_outstanding]  
    window_length = 1
    # Compute market cap value  
    def compute(self, today, assets, out, close, shares):  
        out[:] = close[-1] * shares[-1]
def initialize(context):
    # Create a variable to track the date change
    context.date = None
    context.longs = 0
    
    pipe=Pipeline()
    
    # Construct the custom factor  
    mkt_cap = MarketCap()
    pipe.add(mkt_cap, 'mkt_cap')  
    pipe.add(mkt_cap.rank(ascending=False), 'mkt_cap_rank')

    # Use screen to narrow the universe  
    pipe.set_screen(mkt_cap.top(100))
    #pipe.set_screen(Q1500US())
    
    # Attach to the pipeline
    attach_pipeline(pipe, 'my_pipeline')
    
    for j in range(1, 390, 1):
        #Record positions
        schedule_function(count_positions, date_rules.every_day(), time_rules.market_open(minutes=0+j))
        
    	# Set the sell rules.
    	schedule_function(my_sell, date_rules.every_day(), time_rules.market_open(minutes=1+j))

    	# Set the buy rules.
    	schedule_function(my_buy, date_rules.every_day(), time_rules.market_open(minutes=0+j))

    if usets:
        for i in range(20, 390, 60):    # (low, high, every i minutes)  
            #For taking profit
            schedule_function(take_profit, date_rules.every_day(), time_rules.market_open(minutes=i+5))
            #For stop loss
            schedule_function(stop_loss, date_rules.every_day(), time_rules.market_open(minutes=i+5))
def my_sell(context,data):
    todays_date = get_datetime().date()
    
    # Do nothing unless the date has changed
    #if todays_date == context.date:
    #    return
    # Set the new date
    #context.date = todays_date
    
    #print "Cash: " + str(context.portfolio.cash)
       
    #Iterate and look for oversold
    stockcnt = 0
    for stock in context.portfolio.positions:
       
        stockcnt = stockcnt + 1
        # Load historical data for the stocks
        #data.history(sid(3149), 'open', 10, '1d')
        high = data.history(stock, 'high', bars, '1m')
        low = data.history(stock, 'low', bars, '1m')
        close = data.history(stock, 'close', bars, '1m')
        prices = data.history(stock, 'price', bars, '1m')
        
        if np.all(np.isnan(high)):  continue  
        if np.all(np.isnan(low)):   continue  
        if np.all(np.isnan(close)): continue          
        if np.all(np.isnan(prices)): continue          
        
        #Get out current position on the stock in question
        current_position = context.portfolio.positions[stock].amount
        
        #Look for oversold region
        upper,middle,lower = talib.BBANDS(prices,timeperiod=bbl,nbdevup=mult,nbdevdn=mult,matype=0)
        if np.all(np.isnan(upper)):  continue  
        if np.all(np.isnan(middle)):   continue  
        if np.all(np.isnan(lower)):   continue  

        #EMA
        ema = talib.EMA(close, timeperiod = mal)
        emad = ema[-1] - ema[-2]
        
        if current_position > 0 and (ema[-1] > middle[-1]):
            order_target(stock, 0)
            context.longs = context.longs - 1
            #print "SELLING: " + str(stock)
def my_buy(context,data):
    #todays_date = get_datetime().date()
    
    # Do nothing unless the date has changed
    #if todays_date == context.date:
    #    return
    # Set the new date
    #context.date = todays_date
    
    #print "Cash: " + str(context.portfolio.cash)
       
    #Iterate and look for oversold
    stockcnt = 0
    for stock in context.stocks:
        #Quit the loop if we hit our daily limit
        if context.longs >= numstock:
            return
        
        stockcnt = stockcnt + 1
        # Load historical data for the stocks
        #data.history(sid(3149), 'open', 10, '1d')
        high = data.history(stock, 'high', bars, '1m')
        low = data.history(stock, 'low', bars, '1m')
        close = data.history(stock, 'close', bars, '1m')
        prices = data.history(stock, 'price', bars, '1m')
        
        if np.all(np.isnan(high)):  continue  
        if np.all(np.isnan(low)):   continue  
        if np.all(np.isnan(close)): continue          
        if np.all(np.isnan(prices)): continue          
        
        #Get out current position on the stock in question
        current_position = context.portfolio.positions[stock].amount
        
        #Look for oversold region
        upper,middle,lower = talib.BBANDS(prices,timeperiod=bbl,nbdevup=mult,nbdevdn=mult,matype=0)
        if np.all(np.isnan(upper)):  continue  
        if np.all(np.isnan(middle)):   continue  
        if np.all(np.isnan(lower)):   continue  

        #EMA
        ema = talib.EMA(close, timeperiod = mal)
        emad = ema[-1] - ema[-2]
        
        # Open the order on oversold crossover
        if (emad > 0 and ema[-2] < lower[-2] and ema[-1] >= lower[-1]) and current_position <= 0 and context.longs < numstock:             
            order_target_percent(stock, 1.0/numstock)
            context.longs = context.longs + 1
            #print "BUYING: " + str(stock)           
def take_profit(context, data):    # Close some positions to take profit  
    pos = context.portfolio.positions  
    for s in pos:  
        if not data.can_trade(s): continue  
        prc = data.current(s, 'price')  
        amt = pos[s].amount  
        if (amt / abs(amt)) * ((prc / pos[s].cost_basis) - 1) > takeprofit:  
            order_target(s, 0)  
            if not log: continue  
            log.info('take profit {} {}  cb {}  now {}'.format(  
                amt, s.symbol, '%.2f' % pos[s].cost_basis, prc))  
def stop_loss(context, data):    # Close some positions to take profit  
    pos = context.portfolio.positions  
    for s in pos:  
        if not data.can_trade(s): continue  
        prc = data.current(s, 'price')  
        amt = pos[s].amount  
        if (amt / abs(amt)) * ((prc / pos[s].cost_basis) - 1) < -1*stoploss:  
            order_target(s, 0)  
            if not log: continue  
            log.info('stop loss {} {}  cb {}  now {}'.format(  
                amt, s.symbol, '%.2f' % pos[s].cost_basis, prc))  

            
def count_positions(context,data):
        
    context.longs = 0
    for position in context.portfolio.positions.itervalues():
        if position.amount > 0:
            context.longs += 1
    leverage=context.account.leverage
    # asset=context.portfolio.portfolio_value
    # record(asset=asset)   
    record(longs=context.longs)
    record(leverage=leverage)  
def before_trading_start(context, data):
	context.stocks = pipeline_output('my_pipeline').index.tolist()
There was a runtime error.
7 responses

I know you said you already tried it, but you definitely need to use get_open_orders before placing any buy or sell order to make sure you're not double ordering anyways, so start by puting it back in and see if the problem persists.

Here it is with the get_open_orders, but it has no effect.

Any ideas?

Clone Algorithm
1
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
"""
Buys top market capitalization stocks that are listed as "oversold" and are exiting their oversold region.  Sell when they enter or exit their oversold region.
"""
from quantopian.algorithm import attach_pipeline, pipeline_output
from quantopian.pipeline import Pipeline
from quantopian.pipeline import CustomFactor
from quantopian.pipeline.data import morningstar
from quantopian.pipeline.data.builtin import USEquityPricing
from quantopian.pipeline.factors import AverageDollarVolume
from quantopian.pipeline.filters import Q1500US
import random
import talib
import numpy as np
import pandas as pd
import math
import datetime
from sqlalchemy import or_

#How many stocks?

numstock = 10

#Bollinger band settings
bbl = 20
mult = 2
#MA settings
mal = 3
bars = bbl + mal

log = 0
takeprofit = 0.10
stoploss = 0.05
usets = 0

class MarketCap(CustomFactor):
    # Pre-declare inputs and window_length  
    inputs = [USEquityPricing.close, morningstar.valuation.shares_outstanding]  
    window_length = 1
    # Compute market cap value  
    def compute(self, today, assets, out, close, shares):  
        out[:] = close[-1] * shares[-1]
def initialize(context):
    # Create a variable to track the date change
    context.date = None
    context.longs = 0
    
    pipe=Pipeline()
    
    # Construct the custom factor  
    mkt_cap = MarketCap()
    pipe.add(mkt_cap, 'mkt_cap')  
    pipe.add(mkt_cap.rank(ascending=False), 'mkt_cap_rank')

    # Use screen to narrow the universe  
    pipe.set_screen(mkt_cap.top(100))
    #pipe.set_screen(Q1500US())
    
    # Attach to the pipeline
    attach_pipeline(pipe, 'my_pipeline')
    
    for j in range(1, 390, 1):
        #Record positions
        schedule_function(count_positions, date_rules.every_day(), time_rules.market_open(minutes=0+j))
        
    	# Set the sell rules.
    	schedule_function(my_sell, date_rules.every_day(), time_rules.market_open(minutes=1+j))

    	# Set the buy rules.
    	schedule_function(my_buy, date_rules.every_day(), time_rules.market_open(minutes=0+j))

    if usets:
        for i in range(20, 390, 60):    # (low, high, every i minutes)  
            #For taking profit
            schedule_function(take_profit, date_rules.every_day(), time_rules.market_open(minutes=i+5))
            #For stop loss
            schedule_function(stop_loss, date_rules.every_day(), time_rules.market_open(minutes=i+5))
def my_sell(context,data):
    todays_date = get_datetime().date()
    
    # Do nothing unless the date has changed
    #if todays_date == context.date:
    #    return
    # Set the new date
    #context.date = todays_date
    
    #print "Cash: " + str(context.portfolio.cash)
       
    #Iterate and look for oversold
    stockcnt = 0
    for stock in context.portfolio.positions:
        
        stockcnt = stockcnt + 1
        # Load historical data for the stocks
        #data.history(sid(3149), 'open', 10, '1d')
        high = data.history(stock, 'high', bars, '1m')
        low = data.history(stock, 'low', bars, '1m')
        close = data.history(stock, 'close', bars, '1m')
        prices = data.history(stock, 'price', bars, '1m')
        
        if np.all(np.isnan(high)):  continue  
        if np.all(np.isnan(low)):   continue  
        if np.all(np.isnan(close)): continue          
        if np.all(np.isnan(prices)): continue          
        
        #Get out current position on the stock in question
        current_position = context.portfolio.positions[stock].amount
        
        #Look for oversold region
        upper,middle,lower = talib.BBANDS(prices,timeperiod=bbl,nbdevup=mult,nbdevdn=mult,matype=0)
        if np.all(np.isnan(upper)):  continue  
        if np.all(np.isnan(middle)):   continue  
        if np.all(np.isnan(lower)):   continue  

        #EMA
        ema = talib.EMA(close, timeperiod = mal)
        emad = ema[-1] - ema[-2]
        
        if current_position > 0 and (ema[-1] > middle[-1]):
            order_target(stock, 0)
            context.longs = context.longs - 1
            #print "SELLING: " + str(stock)
def my_buy(context,data):
    #todays_date = get_datetime().date()
    
    # Do nothing unless the date has changed
    #if todays_date == context.date:
    #    return
    # Set the new date
    #context.date = todays_date
    
    #print "Cash: " + str(context.portfolio.cash)
       
    #Iterate and look for oversold
    stockcnt = 0
    for stock in context.stocks:
        #Go to next one in stocks if an order is already open
        if len(get_open_orders(stock)) > 0:
        	continue
            
        #Quit the loop if we hit our daily limit
        if context.longs >= numstock:
            return
        
        stockcnt = stockcnt + 1
        # Load historical data for the stocks
        #data.history(sid(3149), 'open', 10, '1d')
        high = data.history(stock, 'high', bars, '1m')
        low = data.history(stock, 'low', bars, '1m')
        close = data.history(stock, 'close', bars, '1m')
        prices = data.history(stock, 'price', bars, '1m')
        
        if np.all(np.isnan(high)):  continue  
        if np.all(np.isnan(low)):   continue  
        if np.all(np.isnan(close)): continue          
        if np.all(np.isnan(prices)): continue          
        
        #Get out current position on the stock in question
        current_position = context.portfolio.positions[stock].amount
        
        #Look for oversold region
        upper,middle,lower = talib.BBANDS(prices,timeperiod=bbl,nbdevup=mult,nbdevdn=mult,matype=0)
        if np.all(np.isnan(upper)):  continue  
        if np.all(np.isnan(middle)):   continue  
        if np.all(np.isnan(lower)):   continue  

        #EMA
        ema = talib.EMA(close, timeperiod = mal)
        emad = ema[-1] - ema[-2]
        
        # Open the order on oversold crossover
        if (emad > 0 and ema[-2] < lower[-2] and ema[-1] >= lower[-1]) and current_position <= 0 and context.longs < numstock:             
            order_target_percent(stock, 1.0/numstock)
            context.longs = context.longs + 1
            #print "BUYING: " + str(stock)           
def take_profit(context, data):    # Close some positions to take profit  
    pos = context.portfolio.positions  
    for s in pos:  
        if not data.can_trade(s): continue  
        prc = data.current(s, 'price')  
        amt = pos[s].amount  
        if (amt / abs(amt)) * ((prc / pos[s].cost_basis) - 1) > takeprofit:  
            order_target(s, 0)  
            if not log: continue  
            log.info('take profit {} {}  cb {}  now {}'.format(  
                amt, s.symbol, '%.2f' % pos[s].cost_basis, prc))  
def stop_loss(context, data):    # Close some positions to take profit  
    pos = context.portfolio.positions  
    for s in pos:  
        if not data.can_trade(s): continue  
        prc = data.current(s, 'price')  
        amt = pos[s].amount  
        if (amt / abs(amt)) * ((prc / pos[s].cost_basis) - 1) < -1*stoploss:  
            order_target(s, 0)  
            if not log: continue  
            log.info('stop loss {} {}  cb {}  now {}'.format(  
                amt, s.symbol, '%.2f' % pos[s].cost_basis, prc))  

            
def count_positions(context,data):
        
    context.longs = 0
    for position in context.portfolio.positions.itervalues():
        if position.amount > 0:
            context.longs += 1
    leverage=context.account.leverage
    # asset=context.portfolio.portfolio_value
    # record(asset=asset)   
    record(longs=context.longs)
    record(leverage=leverage)  
def before_trading_start(context, data):
	context.stocks = pipeline_output('my_pipeline').index.tolist()
There was a runtime error.

Seemed to be in the right direction

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
"""
Buys top market capitalization stocks that are listed as "oversold" and are exiting their oversold region.  Sell when they enter or exit their oversold region.
"""
from quantopian.algorithm import attach_pipeline, pipeline_output
from quantopian.pipeline import Pipeline
from quantopian.pipeline import CustomFactor
from quantopian.pipeline.data import morningstar
from quantopian.pipeline.data.builtin import USEquityPricing
from quantopian.pipeline.factors import AverageDollarVolume
from quantopian.pipeline.filters import Q1500US
import random
import talib
import numpy as np
import pandas as pd
import math
import datetime
from sqlalchemy import or_

#How many stocks?

numstock = 10

#Bollinger band settings
bbl = 60
mult = 2
#MA settings
mal = 3
bars = bbl + mal

log = 0
takeprofit = 0.10
stoploss = 0.05
usets = 0

class MarketCap(CustomFactor):
    # Pre-declare inputs and window_length
    inputs = [USEquityPricing.close, morningstar.valuation.shares_outstanding]
    window_length = 1
    # Compute market cap value
    def compute(self, today, assets, out, close, shares):
        out[:] = close[-1] * shares[-1]

def initialize(context):
    # Create a variable to track the date change
    context.date  = None
    context.longs = 0

    pipe=Pipeline()

    # Construct the custom factor
    mkt_cap = MarketCap()
    pipe.add(mkt_cap, 'mkt_cap')
    pipe.add(mkt_cap.rank(ascending=False), 'mkt_cap_rank')

    # Use screen to narrow the universe
    pipe.set_screen(mkt_cap.top(100))
    #pipe.set_screen(Q1500US())

    # Attach to the pipeline
    attach_pipeline(pipe, 'pipeline')

    for j in range(1, 390, 120):
        #Record positions
        schedule_function(count_positions, date_rules.every_day(), time_rules.market_open(minutes=0+j))

        # Set the sell rules.
        schedule_function(sell, date_rules.every_day(), time_rules.market_open(minutes=1+j))

        # Set the buy rules.
        schedule_function(buy,  date_rules.every_day(), time_rules.market_open(minutes=0+j))

    if usets:
        for i in range(20, 390, 60):    # (low, high, every i minutes)
            schedule_function(take_profit, date_rules.every_day(), time_rules.market_open(minutes=i+5))
            schedule_function(stop_loss,   date_rules.every_day(), time_rules.market_open(minutes=i+5))

    for i in range(1, 391):
        schedule_function(pvr, date_rules.every_day(), time_rules.market_open(minutes=i))

def sell(context,data):
    #todays_date = get_datetime().date()
    # Do nothing unless the date has changed
    #if todays_date == context.date:
    #    return
    # Set the new date
    #context.date = todays_date

    #print "Cash: " + str(context.portfolio.cash)

    #Iterate and look for oversold
    stockcnt = 0 
    # Load historical data for the stocks
    #data.history(sid(3149), 'open', 10, '1d')
    if not context.portfolio.positions: return
    pos = context.portfolio.positions.keys()
    #high   = data.history(pos, 'high',  bars, '1m').ffill().bfill()
    #low    = data.history(pos, 'low',   bars, '1m').ffill().bfill()
    close  = data.history(pos, 'close', bars, '1m').ffill().bfill()
    prices = data.history(pos, 'price', bars, '1m').ffill().bfill()


    for s in context.portfolio.positions:

        stockcnt = stockcnt + 1
        #if np.all(np.isnan(high  [s])): continue
        #if np.all(np.isnan(low   [s])): continue
        #if np.all(np.isnan(close [s])): continue
        #if np.all(np.isnan(prices[s])): continue

        # Get current position on the stock in question
        current_position = context.portfolio.positions[s].amount

        # Look for oversold region
        upper, middle, lower = talib.BBANDS(prices[s],timeperiod=bbl,nbdevup=mult,nbdevdn=mult,matype=0)
        if np.all(np.isnan(upper )): continue
        if np.all(np.isnan(middle)): continue
        if np.all(np.isnan(lower )): continue
        if np.all(np.isnan(close[s])): continue

        # EMA
        ema = talib.EMA(close[s], timeperiod = mal)
        #emad = ema[-1] - ema[-2]

        if current_position > 0 and (ema[-1] > middle[-1]):
            order_target(s, 0)
            context.longs = context.longs - 1
            #print "SELLING: " + str(s)

def buy(context,data):
    #todays_date = get_datetime().date()

    # Do nothing unless the date has changed
    #if todays_date == context.date:
    #    return
    # Set the new date
    #context.date = todays_date

    #print "Cash: " + str(context.portfolio.cash)

    #Iterate and look for oversold
    stockcnt = 0
    # Load historical data for the stocks
    #data.history(sid(3149), 'open', 10, '1d')
    pos = context.stocks
    #high   = data.history(pos, 'high',  bars, '1m').ffill().bfill()
    #low    = data.history(pos, 'low',   bars, '1m').ffill().bfill()
    close  = data.history(pos, 'close', bars, '1m').ffill().bfill()
    prices = data.history(pos, 'price', bars, '1m').ffill().bfill()

    for s in context.stocks:
        # Go to next one in stocks if an order is already open
        if get_open_orders(s):
            continue

        #Quit the loop if we hit our daily limit
        if context.longs >= numstock:
            return

        stockcnt = stockcnt + 1
        #if np.all(np.isnan(high  [s])): continue
        #if np.all(np.isnan(low   [s])): continue
        #if np.all(np.isnan(close [s])): continue
        #if np.all(np.isnan(prices[s])): continue

        # Get current position on the stock in question
        current_position = context.portfolio.positions[s].amount

        # Look for oversold region
        upper, middle, lower = talib.BBANDS(prices[s],timeperiod=bbl,nbdevup=mult,nbdevdn=mult,matype=0)
        if np.all(np.isnan(upper )): continue
        if np.all(np.isnan(middle)): continue
        if np.all(np.isnan(lower )): continue
        if np.all(np.isnan(close[s])): continue

        # EMA
        ema = talib.EMA(close[s], timeperiod = mal)
        emad = ema[-1] - ema[-2]

        # Open the order on oversold crossover
        if (emad > 0 and ema[-2] < lower[-2] and ema[-1] >= lower[-1]) and current_position <= 0 and context.longs < numstock:
            order_target_percent(s, 1.0 / numstock)
            context.longs = context.longs + 1
            #print "BUYING: " + str(s)

def take_profit(context, data):    # Close some positions to take profit
    pos = context.portfolio.positions
    for s in pos:
        if not data.can_trade(s): continue
        prc = data.current(s, 'price')
        amt = pos[s].amount
        if (amt / abs(amt)) * ((prc / pos[s].cost_basis) - 1) > takeprofit:
            order_target(s, 0)
            #if not log: continue
            #log.info('take profit {} {}  cb {}  now {}'.format(
            #    amt, s.symbol, '%.2f' % pos[s].cost_basis, prc))

def stop_loss(context, data):      # Close some positions to prevent loss
    pos = context.portfolio.positions
    for s in pos:
        if not data.can_trade(s): continue
        prc = data.current(s, 'price')
        amt = pos[s].amount
        if (amt / abs(amt)) * ((prc / pos[s].cost_basis) - 1) < -1*stoploss:
            order_target(s, 0)
            #if not log: continue
            #log.info('stop loss {} {}  cb {}  now {}'.format(
            #    amt, s.symbol, '%.2f' % pos[s].cost_basis, prc))

def count_positions(context,data):
    #leverage=context.account.leverage
    # asset=context.portfolio.portfolio_value
    # record(asset=asset)
    context.longs = len([s for s, pos in context.portfolio.positions.items() if pos.amount > 0])
    record(longs=context.longs)
    #record(leverage=leverage)

def before_trading_start(context, data):
    context.stocks = pipeline_output('pipeline').dropna().index.tolist()
    
def pvr(context, data):
    ''' Custom chart and/or logging of profit_vs_risk returns and related information
    '''
    import time
    from datetime import datetime as _dt
    from pytz import timezone      # Python will only do once, makes this portable.
                                   #   Move to top of algo for better efficiency.
    c = context  # Brevity is the soul of wit -- Shakespeare [for readability]
    if 'pvr' not in c:

        # For real money, you can modify this to total cash input minus any withdrawals
        manual_cash = c.portfolio.starting_cash
        time_zone   = 'US/Pacific'   # Optionally change to your own time zone for wall clock time

        c.pvr = {
            'options': {
                # # # # # # # # # #  Options  # # # # # # # # # #
                'logging'         : 0,    # Info to logging window with some new maximums
                'log_summary'     : 126,  # Summary every x days. 252/yr

                'record_pvr'      : 1,    # Profit vs Risk returns (percentage)
                'record_pvrp'     : 0,    # PvR (p)roportional neg cash vs portfolio value
                'record_cash'     : 0,    # Cash available
                'record_max_lvrg' : 1,    # Maximum leverage encountered
                'record_max_risk' : 0,    # Highest risk overall
                'record_shorting' : 0,    # Total value of any shorts
                'record_max_shrt' : 0,    # Max value of shorting total
                'record_cash_low' : 1,    # Any new lowest cash level
                'record_q_return' : 0,    # Quantopian returns (percentage)
                'record_pnl'      : 0,    # Profit-n-Loss
                'record_risk'     : 0,    # Risked, max cash spent or shorts beyond longs+cash
                'record_leverage' : 1,    # End of day leverage (context.account.leverage)
                # All records are end-of-day or the last data sent to chart during any day.
                # The way the chart operates, only the last value of the day will be seen.
                # # # # # # # # #  End options  # # # # # # # # #
            },
            'pvr'        : 0,      # Profit vs Risk returns based on maximum spent
            'cagr'       : 0,
            'max_lvrg'   : 0,
            'max_shrt'   : 0,
            'max_risk'   : 0,
            'days'       : 0.0,
            'date_prv'   : '',
            'date_end'   : get_environment('end').date(),
            'cash_low'   : manual_cash,
            'cash'       : manual_cash,
            'start'      : manual_cash,
            'tz'         : time_zone,
            'begin'      : time.time(),  # For run time
            'run_str'    : '{} to {}  ${}  {} {}'.format(get_environment('start').date(), get_environment('end').date(), int(manual_cash), _dt.now(timezone(time_zone)).strftime("%Y-%m-%d %H:%M"), time_zone)
        }
        if c.pvr['options']['record_pvrp']: c.pvr['options']['record_pvr'] = 0 # if pvrp is active, straight pvr is off
        if get_environment('arena') not in ['backtest', 'live']: c.pvr['options']['log_summary'] = 1 # Every day when real money
        log.info(c.pvr['run_str'])
    p = c.pvr ; o = c.pvr['options'] ; pf = c.portfolio ; pnl = pf.portfolio_value - p['start']
    def _pvr(c):
        p['cagr'] = ((pf.portfolio_value / p['start']) ** (1 / (p['days'] / 252.))) - 1
        ptype = 'PvR' if o['record_pvr'] else 'PvRp'
        log.info('{} {} %/day   cagr {}   Portfolio value {}   PnL {}'.format(ptype, '%.4f' % (p['pvr'] / p['days']), '%.3f' % p['cagr'], '%.0f' % pf.portfolio_value, '%.0f' % pnl))
        log.info('  Profited {} on {} activated/transacted for PvR of {}%'.format('%.0f' % pnl, '%.0f' % p['max_risk'], '%.1f' % p['pvr']))
        log.info('  QRet {} PvR {} CshLw {} MxLv {} MxRisk {} MxShrt {}'.format('%.2f' % (100 * pf.returns), '%.2f' % p['pvr'], '%.0f' % p['cash_low'], '%.2f' % p['max_lvrg'], '%.0f' % p['max_risk'], '%.0f' % p['max_shrt']))
    def _minut():
        dt = get_datetime().astimezone(timezone(p['tz']))
        return str((dt.hour * 60) + dt.minute - 570).rjust(3)  # (-570 = 9:31a)
    date = get_datetime().date()
    if p['date_prv'] != date:
        p['date_prv'] = date
        p['days'] += 1.0
    do_summary = 0
    if o['log_summary'] and p['days'] % o['log_summary'] == 0 and _minut() == '100':
        do_summary = 1              # Log summary every x days
    if do_summary or date == p['date_end']:
        p['cash'] = pf.cash
    elif p['cash'] == pf.cash and not o['logging']: return  # for speed

    shorts = sum([z.amount * z.last_sale_price for s, z in pf.positions.items() if z.amount < 0])
    new_key_hi = 0                  # To trigger logging if on.
    cash       = pf.cash
    cash_dip   = int(max(0, p['start'] - cash))
    risk       = int(max(cash_dip, -shorts))

    if o['record_pvrp'] and cash < 0:   # Let negative cash ding less when portfolio is up.
        cash_dip = int(max(0, cash_dip * p['start'] / pf.portfolio_value))
        # Imagine: Start with 10, grows to 1000, goes negative to -10, should not be 200% risk.

    if int(cash) < p['cash_low']:             # New cash low
        new_key_hi = 1
        p['cash_low'] = int(cash)             # Lowest cash level hit
        if o['record_cash_low']: record(CashLow = p['cash_low'])

    if c.account.leverage > p['max_lvrg']:
        new_key_hi = 1
        p['max_lvrg'] = c.account.leverage    # Maximum intraday leverage
        if o['record_max_lvrg']: record(MxLv    = p['max_lvrg'])

    if shorts < p['max_shrt']:
        new_key_hi = 1
        p['max_shrt'] = shorts                # Maximum shorts value
        if o['record_max_shrt']: record(MxShrt  = p['max_shrt'])

    if risk > p['max_risk']:
        new_key_hi = 1
        p['max_risk'] = risk                  # Highest risk overall
        if o['record_max_risk']:  record(MxRisk = p['max_risk'])

    # Profit_vs_Risk returns based on max amount actually invested, long or short
    if p['max_risk'] != 0: # Avoid zero-divide
        p['pvr'] = 100 * pnl / p['max_risk']
        ptype = 'PvRp' if o['record_pvrp'] else 'PvR'
        if o['record_pvr'] or o['record_pvrp']: record(**{ptype: p['pvr']})

    if o['record_shorting']: record(Shorts = shorts)             # Shorts value as a positve
    if o['record_leverage']: record(Lv     = c.account.leverage) # Leverage
    if o['record_cash']    : record(Cash   = cash)               # Cash
    if o['record_risk']    : record(Risk   = risk)  # Amount in play, maximum of shorts or cash used
    if o['record_q_return']: record(QRet   = 100 * pf.returns)
    if o['record_pnl']     : record(PnL    = pnl)                # Profit|Loss

    if o['logging'] and new_key_hi:
        log.info('{}{}{}{}{}{}{}{}{}{}{}{}'.format(_minut(),
            ' Lv '     + '%.1f' % c.account.leverage,
            ' MxLv '   + '%.2f' % p['max_lvrg'],
            ' QRet '   + '%.1f' % (100 * pf.returns),
            ' PvR '    + '%.1f' % p['pvr'],
            ' PnL '    + '%.0f' % pnl,
            ' Cash '   + '%.0f' % cash,
            ' CshLw '  + '%.0f' % p['cash_low'],
            ' Shrt '   + '%.0f' % shorts,
            ' MxShrt ' + '%.0f' % p['max_shrt'],
            ' Risk '   + '%.0f' % risk,
            ' MxRisk ' + '%.0f' % p['max_risk']
        ))
    if do_summary: _pvr(c)
    if get_datetime() == get_environment('end'):   # Summary at end of run
        _pvr(c) ; elapsed = (time.time() - p['begin']) / 60  # minutes
        log.info( '{}\nRuntime {} hr {} min'.format(p['run_str'], int(elapsed / 60), '%.1f' % (elapsed % 60)))
 
There was a runtime error.

Further changes went off the rails, I'll leave it to you

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
"""
Buys top market capitalization stocks that are listed as "oversold" and are exiting their oversold region.  Sell when they enter or exit their oversold region.
"""
from quantopian.algorithm import attach_pipeline, pipeline_output
from quantopian.pipeline import Pipeline
from quantopian.pipeline import CustomFactor
from quantopian.pipeline.data import morningstar
from quantopian.pipeline.data.builtin import USEquityPricing
from quantopian.pipeline.factors import AverageDollarVolume
from quantopian.pipeline.filters import Q1500US
import random
import talib
import numpy as np
import pandas as pd
import math
import datetime
from sqlalchemy import or_

#How many stocks?

numstock = 10

#Bollinger band settings
bbl = 60
mult = 2
#MA settings
mal = 3
bars = bbl + mal

log = 0
takeprofit = 0.10
stoploss = 0.05
usets = 0

class MarketCap(CustomFactor):
    # Pre-declare inputs and window_length
    inputs = [USEquityPricing.close, morningstar.valuation.shares_outstanding]
    window_length = 1
    # Compute market cap value
    def compute(self, today, assets, out, close, shares):
        out[:] = close[-1] * shares[-1]

def initialize(context):
    # Create a variable to track the date change
    context.date  = None
    context.longs = 0

    pipe=Pipeline()

    # Construct the custom factor
    mkt_cap = MarketCap()
    pipe.add(mkt_cap, 'mkt_cap')
    pipe.add(mkt_cap.rank(ascending=False), 'mkt_cap_rank')

    # Use screen to narrow the universe
    pipe.set_screen(mkt_cap.top(100))
    #pipe.set_screen(Q1500US())

    # Attach to the pipeline
    attach_pipeline(pipe, 'pipeline')

    for j in range(1, 390, 20):
        # Record positions
        schedule_function(count_positions, date_rules.every_day(), time_rules.market_open(minutes=0+j))

        # Set the sell rules.
        schedule_function(sell, date_rules.every_day(), time_rules.market_open(minutes=1+j))

        # Set the buy rules.
        schedule_function(buy,  date_rules.every_day(), time_rules.market_open(minutes=0+j))

    if usets:
        for i in range(20, 390, 60):    # (low, high, every i minutes)
            schedule_function(take_profit, date_rules.every_day(), time_rules.market_open(minutes=i+5))
            schedule_function(stop_loss,   date_rules.every_day(), time_rules.market_open(minutes=i+5))

    for i in range(1, 391):
        schedule_function(pvr, date_rules.every_day(), time_rules.market_open(minutes=i))

def sell(context,data):
    #todays_date = get_datetime().date()
    # Do nothing unless the date has changed
    #if todays_date == context.date:
    #    return
    # Set the new date
    #context.date = todays_date

    #print "Cash: " + str(context.portfolio.cash)

    # Iterate and look for oversold
    stockcnt = 0 
    # Load historical data for the stocks
    #data.history(sid(3149), 'open', 10, '1d')
    if not context.portfolio.positions: return
    pos    = context.portfolio.positions.keys()
    prices = data.history(pos, 'price', bars, '1m').ffill(axis=1).bfill(axis=1)

    for s in context.portfolio.positions:
        stockcnt = stockcnt + 1

        # Get current position on the stock in question
        current_position = context.portfolio.positions[s].amount

        # Look for oversold region
        upper, middle, lower = talib.BBANDS(prices[s],timeperiod=bbl,nbdevup=mult,nbdevdn=mult,matype=0)

        # EMA
        ema = talib.EMA(prices[s], timeperiod = mal)

        if current_position > 0 and (ema[-1] > middle[-1]):
            order_target(s, 0)
            #print "SELLING: " + str(s)

def buy(context,data):
    #todays_date = get_datetime().date()
    # Do nothing unless the date has changed
    #if todays_date == context.date:
    #    return
    # Set the new date
    #context.date = todays_date

    #print "Cash: " + str(context.portfolio.cash)

    # Iterate and look for oversold
    stockcnt = 0
    pos = context.portfolio.positions.keys()
    numstock = len(set(list(context.stocks.index) + pos))  # set makes unique
    sids     = context.stocks.index
    prices   = data.history(sids, 'price', bars, '1m').ffill(axis=1).bfill(axis=1)

    for s in context.stocks.index:
        # Go to next in stocks if an order is already open
        if get_open_orders(s): continue

        # Quit the loop if hit daily limit
        if context.longs >= numstock:
            break

        stockcnt = stockcnt + 1

        # Get current position on the stock in question
        current_position = context.portfolio.positions[s].amount

        # Look for oversold region
        upper, middle, lower = talib.BBANDS(prices[s],timeperiod=bbl,nbdevup=mult,nbdevdn=mult,matype=0)

        # EMA
        ema  = talib.EMA(prices[s], timeperiod = mal)
        emad = ema[-1] - ema[-2]

        # Open the order on oversold crossover
        if (emad > 0 and ema[-2] < lower[-2] and ema[-1] >= lower[-1]) and current_position <= 0 and context.longs < numstock:
            order_target_percent(s, 1.0 / numstock)
            #print "BUYING: " + str(s)

def take_profit(context, data):    # Close some positions to take profit
    pos = context.portfolio.positions
    for s in pos:
        if not data.can_trade(s): continue
        prc = data.current(s, 'price')
        amt = pos[s].amount
        if (amt / abs(amt)) * ((prc / pos[s].cost_basis) - 1) > takeprofit:
            order_target(s, 0)
            #if not log: continue
            #log.info('take profit {} {}  cb {}  now {}'.format(
            #    amt, s.symbol, '%.2f' % pos[s].cost_basis, prc))

def stop_loss(context, data):      # Close some positions to prevent loss
    pos = context.portfolio.positions
    for s in pos:
        if not data.can_trade(s): continue
        prc = data.current(s, 'price')
        amt = pos[s].amount
        if (amt / abs(amt)) * ((prc / pos[s].cost_basis) - 1) < -1*stoploss:
            order_target(s, 0)
            #if not log: continue
            #log.info('stop loss {} {}  cb {}  now {}'.format(
            #    amt, s.symbol, '%.2f' % pos[s].cost_basis, prc))

def count_positions(context,data):
    #leverage=context.account.leverage
    # asset=context.portfolio.portfolio_value
    # record(asset=asset)
    context.longs = len([s for s, pos in context.portfolio.positions.items() if pos.amount > 0])
    record(longs=context.longs)
    #record(leverage=leverage)

def before_trading_start(context, data):
    context.stocks = pipeline_output('pipeline').dropna()
    
def pvr(context, data):
    ''' Custom chart and/or logging of profit_vs_risk returns and related information
    '''
    import time
    from datetime import datetime as _dt
    from pytz import timezone      # Python will only do once, makes this portable.
                                   #   Move to top of algo for better efficiency.
    c = context  # Brevity is the soul of wit -- Shakespeare [for readability]
    if 'pvr' not in c:

        # For real money, you can modify this to total cash input minus any withdrawals
        manual_cash = c.portfolio.starting_cash
        time_zone   = 'US/Pacific'   # Optionally change to your own time zone for wall clock time

        c.pvr = {
            'options': {
                # # # # # # # # # #  Options  # # # # # # # # # #
                'logging'         : 0,    # Info to logging window with some new maximums
                'log_summary'     : 126,  # Summary every x days. 252/yr

                'record_pvr'      : 1,    # Profit vs Risk returns (percentage)
                'record_pvrp'     : 0,    # PvR (p)roportional neg cash vs portfolio value
                'record_cash'     : 0,    # Cash available
                'record_max_lvrg' : 1,    # Maximum leverage encountered
                'record_max_risk' : 0,    # Highest risk overall
                'record_shorting' : 0,    # Total value of any shorts
                'record_max_shrt' : 0,    # Max value of shorting total
                'record_cash_low' : 1,    # Any new lowest cash level
                'record_q_return' : 0,    # Quantopian returns (percentage)
                'record_pnl'      : 0,    # Profit-n-Loss
                'record_risk'     : 0,    # Risked, max cash spent or shorts beyond longs+cash
                'record_leverage' : 1,    # End of day leverage (context.account.leverage)
                # All records are end-of-day or the last data sent to chart during any day.
                # The way the chart operates, only the last value of the day will be seen.
                # # # # # # # # #  End options  # # # # # # # # #
            },
            'pvr'        : 0,      # Profit vs Risk returns based on maximum spent
            'cagr'       : 0,
            'max_lvrg'   : 0,
            'max_shrt'   : 0,
            'max_risk'   : 0,
            'days'       : 0.0,
            'date_prv'   : '',
            'date_end'   : get_environment('end').date(),
            'cash_low'   : manual_cash,
            'cash'       : manual_cash,
            'start'      : manual_cash,
            'tz'         : time_zone,
            'begin'      : time.time(),  # For run time
            'run_str'    : '{} to {}  ${}  {} {}'.format(get_environment('start').date(), get_environment('end').date(), int(manual_cash), _dt.now(timezone(time_zone)).strftime("%Y-%m-%d %H:%M"), time_zone)
        }
        if c.pvr['options']['record_pvrp']: c.pvr['options']['record_pvr'] = 0 # if pvrp is active, straight pvr is off
        if get_environment('arena') not in ['backtest', 'live']: c.pvr['options']['log_summary'] = 1 # Every day when real money
        log.info(c.pvr['run_str'])
    p = c.pvr ; o = c.pvr['options'] ; pf = c.portfolio ; pnl = pf.portfolio_value - p['start']
    def _pvr(c):
        p['cagr'] = ((pf.portfolio_value / p['start']) ** (1 / (p['days'] / 252.))) - 1
        ptype = 'PvR' if o['record_pvr'] else 'PvRp'
        log.info('{} {} %/day   cagr {}   Portfolio value {}   PnL {}'.format(ptype, '%.4f' % (p['pvr'] / p['days']), '%.3f' % p['cagr'], '%.0f' % pf.portfolio_value, '%.0f' % pnl))
        log.info('  Profited {} on {} activated/transacted for PvR of {}%'.format('%.0f' % pnl, '%.0f' % p['max_risk'], '%.1f' % p['pvr']))
        log.info('  QRet {} PvR {} CshLw {} MxLv {} MxRisk {} MxShrt {}'.format('%.2f' % (100 * pf.returns), '%.2f' % p['pvr'], '%.0f' % p['cash_low'], '%.2f' % p['max_lvrg'], '%.0f' % p['max_risk'], '%.0f' % p['max_shrt']))
    def _minut():
        dt = get_datetime().astimezone(timezone(p['tz']))
        return str((dt.hour * 60) + dt.minute - 570).rjust(3)  # (-570 = 9:31a)
    date = get_datetime().date()
    if p['date_prv'] != date:
        p['date_prv'] = date
        p['days'] += 1.0
    do_summary = 0
    if o['log_summary'] and p['days'] % o['log_summary'] == 0 and _minut() == '100':
        do_summary = 1              # Log summary every x days
    if do_summary or date == p['date_end']:
        p['cash'] = pf.cash
    elif p['cash'] == pf.cash and not o['logging']: return  # for speed

    shorts = sum([z.amount * z.last_sale_price for s, z in pf.positions.items() if z.amount < 0])
    new_key_hi = 0                  # To trigger logging if on.
    cash       = pf.cash
    cash_dip   = int(max(0, p['start'] - cash))
    risk       = int(max(cash_dip, -shorts))

    if o['record_pvrp'] and cash < 0:   # Let negative cash ding less when portfolio is up.
        cash_dip = int(max(0, cash_dip * p['start'] / pf.portfolio_value))
        # Imagine: Start with 10, grows to 1000, goes negative to -10, should not be 200% risk.

    if int(cash) < p['cash_low']:             # New cash low
        new_key_hi = 1
        p['cash_low'] = int(cash)             # Lowest cash level hit
        if o['record_cash_low']: record(CashLow = p['cash_low'])

    if c.account.leverage > p['max_lvrg']:
        new_key_hi = 1
        p['max_lvrg'] = c.account.leverage    # Maximum intraday leverage
        if o['record_max_lvrg']: record(MxLv    = p['max_lvrg'])

    if shorts < p['max_shrt']:
        new_key_hi = 1
        p['max_shrt'] = shorts                # Maximum shorts value
        if o['record_max_shrt']: record(MxShrt  = p['max_shrt'])

    if risk > p['max_risk']:
        new_key_hi = 1
        p['max_risk'] = risk                  # Highest risk overall
        if o['record_max_risk']:  record(MxRisk = p['max_risk'])

    # Profit_vs_Risk returns based on max amount actually invested, long or short
    if p['max_risk'] != 0: # Avoid zero-divide
        p['pvr'] = 100 * pnl / p['max_risk']
        ptype = 'PvRp' if o['record_pvrp'] else 'PvR'
        if o['record_pvr'] or o['record_pvrp']: record(**{ptype: p['pvr']})

    if o['record_shorting']: record(Shorts = shorts)             # Shorts value as a positve
    if o['record_leverage']: record(Lv     = c.account.leverage) # Leverage
    if o['record_cash']    : record(Cash   = cash)               # Cash
    if o['record_risk']    : record(Risk   = risk)  # Amount in play, maximum of shorts or cash used
    if o['record_q_return']: record(QRet   = 100 * pf.returns)
    if o['record_pnl']     : record(PnL    = pnl)                # Profit|Loss

    if o['logging'] and new_key_hi:
        log.info('{}{}{}{}{}{}{}{}{}{}{}{}'.format(_minut(),
            ' Lv '     + '%.1f' % c.account.leverage,
            ' MxLv '   + '%.2f' % p['max_lvrg'],
            ' QRet '   + '%.1f' % (100 * pf.returns),
            ' PvR '    + '%.1f' % p['pvr'],
            ' PnL '    + '%.0f' % pnl,
            ' Cash '   + '%.0f' % cash,
            ' CshLw '  + '%.0f' % p['cash_low'],
            ' Shrt '   + '%.0f' % shorts,
            ' MxShrt ' + '%.0f' % p['max_shrt'],
            ' Risk '   + '%.0f' % risk,
            ' MxRisk ' + '%.0f' % p['max_risk']
        ))
    if do_summary: _pvr(c)
    if get_datetime() == get_environment('end'):   # Summary at end of run
        _pvr(c) ; elapsed = (time.time() - p['begin']) / 60  # minutes
        log.info( '{}\nRuntime {} hr {} min'.format(p['run_str'], int(elapsed / 60), '%.1f' % (elapsed % 60)))
 
There was a runtime error.

Looks like order_target_percent(stock, 1.0/numstock) is ordering 10% of portfolio value for each stock no matter how many stocks are returned by pipeline, since numstock is simply set to 10. Another thing to be careful about is a situation where you get 10 stocks from pipeline, give each 10% weight, then the next day you get 10 more stocks from pipeline and give each of those 10% weight... since not all the stocks from the day before have sold, you are now over 100% total leverage.

Thanks for working on this guys. It was super helpful. Even if the algorithm didn't work exactly as I had planned, it is still a huge help!

Cool. Meanwhile now that it's no longer 3 AM and I'm more awake, maybe the ... '1m').ffill(axis=1).bfill(axis=1) isn't doing anything as I understand prices are forward filled. Might want to use 'close', not forward filled and count nans to skip any stock currently above some threshold percentage of nans. If that route, then they do need ffill afterward and before ema and bbands calcs. Since the history call has been moved outside of the loop and is operating on the entire list of stocks instead of one at a time, if it were 'close' instead of 'price', the axis=1 may be required to prevent action on all stocks whenever one stock needs the fill. I would test in the debugger with just a few stocks and small window to find out for sure.

@VHawk, right on. And I'm trying to imagine a way to avoid closing where take profit and stop loss would rule the closings, a universal function that could adopt incoming stocks with new weights and adjust everybody else in some sensible way based on their current weights maybe. Complicated.

Here since numstock in order_target_percent(stock, 1.0/numstock) is just an integer with equal weights, it could be replaced with len(set(list(c.stocks) + c.portfolio.positions.keys()))where c is context, and set makes unique, toward being able to keep on adding positions.