Help converting an old algorithm from quantopian

Hi all,

I found an old script on quantopian that I wanted to test. I have tried to convert it as best as I could to use with pylivetrader but still getting errors. I am not a coder and am still learning so it might just be something simple that I’m overlooking.

Anyways if any of you can help with the script below, I would greatly appreciate it.

TIA.

from pylivetrader.api import *
from logbook import Logger, StreamHandler
import sys
StreamHandler(sys.stdout).push_application()
log = Logger(__name__)
import numpy as np
import talib
import copy
import math
import datetime as dt
from datetime import datetime, timedelta, date
from pipeline_live.data.iex.pricing import USEquityPricing
from pipeline_live.data.iex.fundamentals import IEXCompany, IEXKeyStats
from pipeline_live.data.iex.factors import (
    SimpleMovingAverage, AverageDollarVolume, RSI, CustomFactor, Latest, AverageDollarVolume
)
import os
 
class atr_10days_percent(CustomFactor):  
    inputs = [USEquityPricing.high, USEquityPricing.low, USEquityPricing.close]  
    window_length = 11  
    def compute(self, today, assets, out, high, low, close):  
        range_high = np.maximum(high[1:], close[:-1]) 
        range_low = np.minimum(low[1:], close[:-1])  
        out[:] = np.mean(((range_high - range_low)/close[:-1])*100, axis=0) 
        
class atr_10days(CustomFactor):
    inputs = [USEquityPricing.high, USEquityPricing.low, USEquityPricing.close]  
    window_length = 11  
    def compute(self, today, assets, out, high, low, close):  
        range_high = np.maximum(high[1:], close[:-1])
        range_low = np.minimum(low[1:], close[:-1])
        out[:] = np.mean(range_high - range_low, axis=0)  
 
def initialize(context):
    set_long_only()
 
    schedule_function(sell, date_rules.every_day(), time_rules.market_open(hours=0, minutes=5), half_days=False)
    schedule_function(buy, date_rules.every_day(), time_rules.market_open(hours=0, minutes=59), half_days=False)
    schedule_function(cancel_open_orders, date_rules.every_day(), time_rules.market_close(minutes=1), half_days=False)
    schedule_function(my_record_vars, date_rules.every_day(), time_rules.market_close(), half_days=False)
    my_pipe = make_pipeline()
    attach_pipeline(my_pipe, 'my_pipeline')
    #attach_pipeline(make_pipeline(pipe), 'my_pipeline')
    
    context.first_time = True
    context.tracker = dict()  
    context.tmp_tracker= dict()
    
def make_pipeline():
    have_market_cap = IEXKeyStats.marketcap.latest.notnull()
    
    avg_volume = SimpleMovingAverage(inputs=[USEquityPricing.volume],window_length=50)
    filter_volume = avg_volume > 500000
    
    last_price = Latest(inputs=[USEquityPricing.close], window_length=1) 
    filter_price = last_price > 1
    
    dollar_volume = AverageDollarVolume(window_length=50)
    filter_dollar_volume = dollar_volume > 2500000
    
    sma_150 = SimpleMovingAverage(inputs=[USEquityPricing.close], window_length=150)
    filter_sma_150 = USEquityPricing.close.latest > sma_150
    
    atr_10_percent = atr_10days_percent()
    filter_atr_10 = atr_10_percent > 4
    
    rsi = RSI(inputs=[USEquityPricing.close], window_length=3)
    filter_overbought = rsi < 30
    
    atr_10 = atr_10days()
    
    stocks_to_trade = have_market_cap & filter_volume & filter_price & filter_dollar_volume & filter_sma_150 & filter_atr_10 & filter_overbought
 
    return Pipeline(
        columns = {
            'stocks': stocks_to_trade,
            'rsi': rsi,
            'atr': atr_10
        },
        screen = (stocks_to_trade),
    )
 
def before_trading_start(context, data):
    context.my_output = pipeline_output('my_pipeline')
    prepare_candidates(context, data)
    
def sell(context, data):
    context.tracker = clean_tracker(context.tracker, context.portfolio.positions)
    add_to_tracker(context.tracker, context.portfolio.positions, context.tmp_tracker)
    increment_day(context.tracker)
    for security in context.portfolio.positions:
        if data.can_trade(security): 
            age = int(context.tracker[security.symbol]['days'])
            if is_expired(age):
                order_target_percent(security, 0)
            else:
                price_share = context.portfolio.positions[security].cost_basis
                atr = float(context.tracker[security.symbol]['atr'])
                stop_loss_price = get_stop_price(price_share, atr)
                if stop_loss_price > 0:
                    order_target_percent(security, 0, style=StopOrder(stop_loss_price)) 
                profit_price = price_share * 1.03
                last_price = context.portfolio.positions[security].last_sale_price
                if last_price >= profit_price:
                    order_target_percent(security, 0)
    context.tmp_tracker = dict()
 
def buy(context, data):
    cash_accum = 0
    for security in context.candidates:
        if security not in context.portfolio.positions and data.can_trade(security): 
            if len(context.portfolio.positions) < 10:
                price_share = data.current(security,'close')                
                cost = get_cost(context.my_output.get_value(security, 'atr'), context.portfolio.portfolio_value, price_share)
                if cost < (context.portfolio.cash - cash_accum) and is_trade(context, data):
                    order_value(security, cost, style=LimitOrder(limit_price=price_share))
                    context.tmp_tracker[security.symbol] = context.my_output.get_value(security, 'atr')
                    cash_accum = cash_accum + cost
                    
def cancel_open_orders(context, data):
    for s in get_open_orders():  
        for o in get_open_orders(s):  
            cancel_order(o) 
 
def my_record_vars(context, data):
    record(cash=context.portfolio.cash)
 
def compute_adx(stock, data):
    period = 7  
    h = data.history(stock,'high', 2*period,'1d').dropna().values  
    l = data.history(stock,'low', 2*period,'1d').dropna().values  
    c = data.history(stock,'close', 2*period,'1d').dropna().values
    if len(h) > 0:
        ta_ADX = talib.ADX(h, l, c, period)  
        adx = ta_ADX[-1]
    else:
        log.warning("No 'highs' for " + str(stock) + ". Discarding the stock when preparing candidates")
        adx = 1000
    return adx
 
def prepare_candidates(context, data): 
    candidates = context.my_output.copy(deep=True)
    to_remove = []
    for index, row in candidates.iterrows():         
        adx = compute_adx(index, data)
        if(adx < 45.0):
            to_remove.append(index)        
    candidates.drop(to_remove, inplace=True)   
    context.candidates = candidates.sort_values('rsi',ascending=True).head(10).index.tolist()
              
def is_trade(context, data):
    i = 0
    for s in get_open_orders():  
        for o in get_open_orders(s):  
            if o.amount > 0:
                i += 1
    i = len(context.portfolio.positions) + i 
    return False if i > 9 else True
 
def handle_data(context, data):
    #just makes sense in Alpaca
    if context.first_time is True:
        if len(context.portfolio.positions) > 0:
            sys.exit("Found positions not traded by the algorithm. Shutting down...")
        if len(get_open_orders()) > 0:
            sys.exit("Found open orders not traded by the algorithm. Shutting down...")
        context.first_time = False
 
def get_stop_price(price, atr):
    p = price - 2.5 * atr
    return 0 if p < 0 else p
 
def is_expired(days):
    return True if days > 4 else False
 
def get_cost(atr, total_value, price_share):       
    stop_loss = get_stop_price(price_share, atr)
    dollar_risk_share = price_share - stop_loss
    cash_to_risk = total_value * 0.02
    num_shares = math.floor(cash_to_risk / dollar_risk_share)
    cost = num_shares * price_share
    max_cost = total_value * 0.1
    if cost > max_cost:
        num_shares = math.floor((total_value * 0.1) / price_share)     
    cost = num_shares * price_share
    return cost
 
def increment_day(tracker):
    for sec in tracker:
        curr_days = int(tracker[sec]['days']) + 1
        tracker[sec]['days'] = str(curr_days)
    return tracker
 
def add_to_tracker(tracker, positions, tmp_tracker):
    for security in positions:
        if not (security.symbol in tracker):
            tracker[security.symbol] = {}
            tracker[security.symbol]['days'] = str(0)
            tracker[security.symbol]['atr'] = str(tmp_tracker[security.symbol])
    return tracker
 
def clean_tracker(tracker, positions):
    to_remove = copy.deepcopy(tracker)
    for sec in tracker:
        found = False
        for sec_pos in positions:
            if sec_pos.symbol == sec:
                found = True
                break
        if found is False:
            to_remove.pop(sec)
    return to_remove

I published this algorithm on Quantopian a long time ago. I also migrated it to Pylivetrader:

The code is quite old tough. I’m sure this won’t work with the current Pylivetrader versions (I don’t even know the current status of Pylivetrader).