Back to Community
Robin Hood Throws A Party

This is a continuation of "The Gold King And His Knights".
This is a slight modification of "The King Forgot His Shorts".

I am now live trading with this instead of the "million percent in 10 years" version.
The final results for that version which I started live trading August 10th is:
Live Trading Robinhood real money "The Gold King And His Knights - million percent in 10 years version"
Started Trading: market open Wednesday, 8/10/2016
Capital base: $1,650.61

As of market close Friday, 9/16/2016
-4.40% Returns / -0.20% Backtest / -2.20% Benchmark
($72.64) Dollar P/L -7.28 Sharpe $627.32 Long Exposure $950.65 Available Cash

Clone Algorithm
76
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.pipeline import Pipeline
from quantopian.algorithm import attach_pipeline, pipeline_output
from quantopian.pipeline.data.builtin import USEquityPricing
from quantopian.pipeline.data import morningstar
from quantopian.pipeline.factors import SimpleMovingAverage, AverageDollarVolume
from quantopian.pipeline.filters.morningstar import IsPrimaryShare

def initialize(context):
    #set_commission(commission.PerShare(cost=0.01, min_trade_cost=1.50))
    set_slippage(slippage.VolumeShareSlippage(volume_limit=.20, price_impact=0.0))
    #set_slippage(slippage.FixedSlippage(spread=0.00))
    set_commission(commission.PerTrade(cost=0.00))
    #set_slippage(slippage.FixedSlippage(spread=0.00))
    set_long_only()

    context.PV=context.portfolio.portfolio_value
    context.NextDay=True
    context.Wait=False
    context.StartingWaitMin=50
    context.WaitMin=context.StartingWaitMin
    context.PipelineWeight=1.00

    schedule_function(StopWait, date_rules.month_start(days_offset=10), time_rules.market_open(hours=0, minutes=7))

    # Record variables at the end of each day.
    schedule_function(my_record_vars, date_rules.every_day(), time_rules.market_close())

    # Create our pipeline and attach it to our algorithm.
    my_pipe = make_pipeline(context)
    attach_pipeline(my_pipe, 'my_pipeline')

def make_pipeline(context):
    """
    Create our pipeline.
    """

    # Filter for primary share equities. IsPrimaryShare is a built-in filter.
    primary_share = IsPrimaryShare()

    # Equities listed as common stock (as opposed to, say, preferred stock).
    # 'ST00000001' indicates common stock.
    common_stock = morningstar.share_class_reference.security_type.latest.eq('ST00000001')

    # Non-depositary receipts. Recall that the ~ operator inverts filters,
    # turning Trues into Falses and vice versa
    not_depositary = ~morningstar.share_class_reference.is_depositary_receipt.latest

    # Equities not trading over-the-counter.
    not_otc = ~morningstar.share_class_reference.exchange_id.latest.startswith('OTC')

    # Not when-issued equities.
    not_wi = ~morningstar.share_class_reference.symbol.latest.endswith('.WI')

    # Equities without LP in their name, .matches does a match using a regular
    # expression
    not_lp_name = ~morningstar.company_reference.standard_name.latest.matches('.* L[. ]?P.?$')

    # Equities with a null value in the limited_partnership Morningstar
    # fundamental field.
    not_lp_balance_sheet = morningstar.balance_sheet.limited_partnership.latest.isnull()

    # Equities whose most recent Morningstar market cap is not null have
    # fundamental data and therefore are not ETFs.
    have_market_cap = morningstar.valuation.market_cap.latest.notnull()

    # At least a certain price
    price = USEquityPricing.close.latest
    AtLeastPrice   = (price >= .20)

    # Filter for stocks that pass all of our previous filters.
    tradeable_stocks = (
        primary_share
        & common_stock
        & not_depositary
        & not_otc
        & not_wi
        & not_lp_name
        & not_lp_balance_sheet
        & have_market_cap
        & AtLeastPrice
    )

    BottomVar=10
    TopVar=10

    LowVar=1
    HighVar=45

    log.info('\nAlgorithm initialized variables:\n BottomVar %s \n TopVar %s \n LowVar %s \n HighVar %s'
        % (BottomVar, TopVar, LowVar, HighVar)
    )
    #record(BottomVar=BottomVar, TopVar=TopVar, LowVar=LowVar, HighVar=HighVar)

    # High dollar volume filter.
    base_universe = AverageDollarVolume(
        window_length=20,
        mask=tradeable_stocks
    ).percentile_between(LowVar, HighVar)

    # Short close price average.
    ShortAvg = SimpleMovingAverage(
        inputs=[USEquityPricing.close],
        window_length=3,
        mask=base_universe
    )

    # Long close price average.
    LongAvg = SimpleMovingAverage(
        inputs=[USEquityPricing.close],
        window_length=45,
        mask=base_universe
    )

    percent_difference = (ShortAvg - LongAvg) / LongAvg

    # Filter to select securities to long.
    stocks_worst = percent_difference.bottom(BottomVar)
    stocks_best = percent_difference.top(TopVar)
    securities_to_trade = (stocks_worst | stocks_best)

    return Pipeline(
        columns={
            'stocks_worst': stocks_worst,
            'stocks_best': stocks_best
        },
        screen=(securities_to_trade),
    )

def my_compute_weights(context):
    """
    Compute ordering weights.
    """
    # Compute even target weights for our long positions and short positions.
    stocks_worst_weight = context.PipelineWeight * 1.00 / len(context.stocks_worst)
    stocks_best_weight = context.PipelineWeight * 0 / len(context.stocks_best)

    return stocks_worst_weight, stocks_best_weight

def before_trading_start(context, data):
    context.NextDay=True

    # Gets our pipeline output every day.
    context.output = pipeline_output('my_pipeline')

    context.stocks_worst = context.output[context.output['stocks_worst']].index.tolist()
    context.stocks_best = context.output[context.output['stocks_best']].index.tolist()

    context.stocks_worst_weight, context.stocks_best_weight = my_compute_weights(context)
    pass

def my_rebalance(context, data):
    GetInFactor=.94
    SSFactor=1.06
    if context.NextDay:

        cash=context.portfolio.cash
        log.info('\n%s   Probable cash balance BEFORE rebalancing buys' % (cash))

        for stock in context.stocks_worst:
            if data.can_trade(stock):
                Curr_P = float(data.current([stock], 'price'))
                if get_open_orders(stock):
                    #log_open_order(stock)
                    continue #do NOT do anything new with this stock until the orders are filled or cancelled at end of day
                if cash >= context.stocks_worst_weight*context.portfolio.portfolio_value:
                    order_value(stock, context.stocks_worst_weight*context.portfolio.portfolio_value,
                        style=LimitOrder(Curr_P*GetInFactor)
                    )
                    cash=cash - (context.stocks_worst_weight*context.portfolio.portfolio_value)

        for stock in context.stocks_best:
            if data.can_trade(stock):
                Curr_P = float(data.current([stock], 'price'))
                if get_open_orders(stock):
                    #log_open_order(stock)
                    continue #do NOT do anything new with this stock until the orders are filled or cancelled at end of day
                if cash >= context.stocks_best_weight*context.portfolio.portfolio_value:
                    order_value(stock, context.stocks_best_weight*context.portfolio.portfolio_value,
                        style=LimitOrder(Curr_P*GetInFactor)
                    )
                    cash=cash - (context.stocks_best_weight*context.portfolio.portfolio_value)

        log.info('\n%s   Probable cash balance AFTER buys and BEFORE sells' % (cash))

        for stock in context.portfolio.positions:
            if stock not in context.stocks_worst and stock not in context.stocks_best and data.can_trade(stock):
                if get_open_orders(stock):
                    continue #do NOT do anything new with this stock until the orders are filled or cancelled at end of day
                StockShares = context.portfolio.positions[stock].amount
                Curr_P = float(data.current([stock], 'price'))
                order(stock, -StockShares,
                    style=LimitOrder(Curr_P)
                )
                #log.info('\nSELLING   %s   shares of   %s' % (StockSharesToSellNow, stock))

        context.NextDay=False

def my_record_vars(context, data):
    """
    Record variables at the end of each day.
    """

    # Record our variables.
    record(MaxPV=context.PV/context.portfolio.starting_cash, leverage=context.account.leverage)
    longs = shorts = 0
    for position in context.portfolio.positions.itervalues():
        if position.amount > 0:
            longs += 1
        if position.amount < 0:
            shorts += 1
    record(long_count=longs, short_count=shorts)


def log_open_order(StockToLog):
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        if stock == StockToLog:
            for order in orders:
                message = 'Found open order for {amount} shares in {stock}'
                log.info(message.format(amount=order.amount, stock=stock))

def log_open_orders():
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        for order in orders:
            message = 'Found open order for {amount} shares in {stock}'
            log.info(message.format(amount=order.amount, stock=stock))

def cancel_open_order(StockToCancel):
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        if stock == StockToCancel:
            for order in orders:
                #message = 'Canceling order of {amount} shares in {stock}'
                #log.info(message.format(amount=order.amount, stock=stock))
                cancel_order(order)
def cancel_open_orders():
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        for order in orders:
            #message = 'Canceling order of {amount} shares in {stock}'
            #log.info(message.format(amount=order.amount, stock=stock))
            cancel_order(order)

#Stop waiting
def StopWait(context, data):
    #The idea is to start fresh
    portfolio_value=context.portfolio.portfolio_value
    context.PV=portfolio_value
    context.Wait=False

# This is the every minute stuff
def handle_data(context, data):
    if context.WaitMin==0:
        context.WaitMin=context.StartingWaitMin

        GetOutFactor=1.25
        cash=context.portfolio.cash
        portfolio_value=context.portfolio.portfolio_value
        if portfolio_value < context.PV*.985 and context.account.leverage>=.33:
            context.Wait=True
            for stock in context.portfolio.positions:
                if data.can_trade(stock):
                    Curr_P = float(data.current([stock], 'price'))
                    if get_open_orders(stock):
                        continue #do NOT do anything new with this stock until the orders are filled or cancelled at end of day
                    if context.NextDay:
                        order_target_percent(stock, 0, style=LimitOrder(Curr_P*GetOutFactor))
        else:
            if portfolio_value > context.PV:
                context.PV=portfolio_value
            context.Wait=False

        # Maybe Take Profit
        if context.NextDay:
            for stock in context.portfolio.positions:
                if data.can_trade(stock):
                    Curr_P = float(data.current([stock], 'price'))
                    if context.portfolio.positions[stock].cost_basis*1.25<Curr_P:
                        if data.can_trade(stock):
                            if get_open_orders(stock):
                                cancel_open_order(stock)
                            order_target_percent(stock, 0, style=LimitOrder(Curr_P*.95))

        if not context.Wait:

            # rebalance if no shares owned or if significant cash available
            if not context.portfolio.positions or (cash >= .50 * portfolio_value) :
                my_rebalance(context, data)

    context.WaitMin-=1
    if context.WaitMin<=0:
        context.WaitMin=0
There was a runtime error.
116 responses

The latest iteration of The King Forgot His Shorts adapted slightly for Robin Hood Throws A Party.
As of now, I am live trading this version.

Clone Algorithm
687
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.pipeline import Pipeline
from quantopian.algorithm import attach_pipeline, pipeline_output
from quantopian.pipeline.data.builtin import USEquityPricing
from quantopian.pipeline.data import morningstar
from quantopian.pipeline.factors import SimpleMovingAverage, AverageDollarVolume
from quantopian.pipeline.filters.morningstar import IsPrimaryShare

def initialize(context):
    #set_commission(commission.PerShare(cost=0.01, min_trade_cost=1.50))
    set_slippage(slippage.VolumeShareSlippage(volume_limit=.20, price_impact=0.0))
    #set_slippage(slippage.FixedSlippage(spread=0.00))
    set_commission(commission.PerTrade(cost=0.00))
    #set_slippage(slippage.FixedSlippage(spread=0.00))
    set_long_only()

    context.PV=context.portfolio.portfolio_value
    context.NextDay=True
    context.Wait=False
    context.StartingWaitMin=50
    context.WaitMin=context.StartingWaitMin
    #context.GIWeight=.66
    context.GIWeight=1.00
    #context.SSWeight=.34
    context.SSWeight=0

    schedule_function(StopWait, date_rules.month_start(days_offset=10), time_rules.market_open(hours=0, minutes=7))

    # Record variables at the end of each day.
    schedule_function(my_record_vars, date_rules.every_day(), time_rules.market_close())

    # Create our pipeline and attach it to our algorithm.
    my_pipe = make_pipeline(context)
    attach_pipeline(my_pipe, 'my_pipeline')

def make_pipeline(context):
    """
    Create our pipeline.
    """

    # Filter for primary share equities. IsPrimaryShare is a built-in filter.
    primary_share = IsPrimaryShare()

    # Equities listed as common stock (as opposed to, say, preferred stock).
    # 'ST00000001' indicates common stock.
    common_stock = morningstar.share_class_reference.security_type.latest.eq('ST00000001')

    # Non-depositary receipts. Recall that the ~ operator inverts filters,
    # turning Trues into Falses and vice versa
    not_depositary = ~morningstar.share_class_reference.is_depositary_receipt.latest

    # Equities not trading over-the-counter.
    not_otc = ~morningstar.share_class_reference.exchange_id.latest.startswith('OTC')

    # Not when-issued equities.
    not_wi = ~morningstar.share_class_reference.symbol.latest.endswith('.WI')

    # Equities without LP in their name, .matches does a match using a regular
    # expression
    not_lp_name = ~morningstar.company_reference.standard_name.latest.matches('.* L[. ]?P.?$')

    # Equities with a null value in the limited_partnership Morningstar
    # fundamental field.
    not_lp_balance_sheet = morningstar.balance_sheet.limited_partnership.latest.isnull()

    # Equities whose most recent Morningstar market cap is not null have
    # fundamental data and therefore are not ETFs.
    have_market_cap = morningstar.valuation.market_cap.latest.notnull()

    # At least a certain price
    price = USEquityPricing.close.latest
    AtLeastPrice   = (.80 <= price <= 3.00)

    # Filter for stocks that pass all of our previous filters.
    tradeable_stocks = (
        primary_share
        & common_stock
        & not_depositary
        & not_otc
        & not_wi
        & not_lp_name
        & not_lp_balance_sheet
        & have_market_cap
        & AtLeastPrice
    )

    BottomVar=10
    TopVar=10

    LowVar=6
    HighVar=40

    log.info('\nAlgorithm initialized variables:\n BottomVar %s \n TopVar %s \n LowVar %s \n HighVar %s'
        % (BottomVar, TopVar, LowVar, HighVar)
    )
    #record(BottomVar=BottomVar, TopVar=TopVar, LowVar=LowVar, HighVar=HighVar)

    # High dollar volume filter.
    base_universe = AverageDollarVolume(
        window_length=20,
        mask=tradeable_stocks
    ).percentile_between(LowVar, HighVar)

    # Short close price average.
    ShortAvg = SimpleMovingAverage(
        inputs=[USEquityPricing.close],
        window_length=3,
        mask=base_universe
    )

    # Long close price average.
    LongAvg = SimpleMovingAverage(
        inputs=[USEquityPricing.close],
        window_length=45,
        mask=base_universe
    )

    percent_difference = (ShortAvg - LongAvg) / LongAvg

    # Filter to select securities to long.
    stocks_worst = percent_difference.bottom(BottomVar)
    stocks_best = percent_difference.top(TopVar)
    securities_to_trade = (stocks_worst | stocks_best)

    return Pipeline(
        columns={
            'stocks_worst': stocks_worst,
            'stocks_best': stocks_best
        },
        screen=(securities_to_trade),
    )

def my_compute_weights(context):
    """
    Compute ordering weights.
    """
    # Compute even target weights for our long positions and short positions.
    stocks_worst_weight = context.GIWeight / len(context.stocks_worst)
    stocks_best_weight = context.SSWeight / len(context.stocks_best)

    return stocks_worst_weight, stocks_best_weight

def before_trading_start(context, data):
    context.NextDay=True

    # Gets our pipeline output every day.
    context.output = pipeline_output('my_pipeline')

    context.stocks_worst = context.output[context.output['stocks_worst']].index.tolist()
    context.stocks_best = context.output[context.output['stocks_best']].index.tolist()

    context.stocks_worst_weight, context.stocks_best_weight = my_compute_weights(context)
    pass

def my_rebalance(context, data):
    GetInFactor=.94
    SSFactor=1.06
    if context.NextDay:

        cash=context.portfolio.cash
        log.info('\n%s   Probable cash balance BEFORE rebalancing buys' % (cash))

        for stock in context.stocks_worst:
            if data.can_trade(stock):
                Curr_P = float(data.current([stock], 'price'))
                if get_open_orders(stock):
                    #log_open_order(stock)
                    continue #do NOT do anything new with this stock until the orders are filled or cancelled at end of day
                if cash >= context.stocks_worst_weight*context.portfolio.portfolio_value:
                    order_value(stock, context.stocks_worst_weight*context.portfolio.portfolio_value,
                        style=LimitOrder(Curr_P*GetInFactor)
                    )
                    cash=cash - (context.stocks_worst_weight*context.portfolio.portfolio_value)

        for stock in context.stocks_best:
            if data.can_trade(stock):
                Curr_P = float(data.current([stock], 'price'))
                if get_open_orders(stock):
                    #log_open_order(stock)
                    continue #do NOT do anything new with this stock until the orders are filled or cancelled at end of day
                if cash >= context.stocks_best_weight*context.portfolio.portfolio_value:
                    order_value(stock, -context.stocks_best_weight*context.portfolio.portfolio_value,
                        style=LimitOrder(Curr_P*SSFactor)
                    )
                    cash=cash - (context.stocks_best_weight*context.portfolio.portfolio_value)

        log.info('\n%s   Probable cash balance AFTER buys and BEFORE sells' % (cash))

        for stock in context.portfolio.positions:
            if stock not in context.stocks_worst and stock not in context.stocks_best and data.can_trade(stock):
                if get_open_orders(stock):
                    continue #do NOT do anything new with this stock until the orders are filled or cancelled at end of day
                StockShares = context.portfolio.positions[stock].amount
                Curr_P = float(data.current([stock], 'price'))
                order(stock, -StockShares,
                    style=LimitOrder(Curr_P)
                )
                #log.info('\nSELLING   %s   shares of   %s' % (StockSharesToSellNow, stock))

        context.NextDay=False

def my_record_vars(context, data):
    """
    Record variables at the end of each day.
    """

    # Record our variables.
    record(MaxPV=context.PV/context.portfolio.starting_cash, leverage=context.account.leverage)
    longs = shorts = 0
    for position in context.portfolio.positions.itervalues():
        if position.amount > 0:
            longs += 1
        if position.amount < 0:
            shorts += 1
    record(long_count=longs, short_count=shorts)


def log_open_order(StockToLog):
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        if stock == StockToLog:
            for order in orders:
                message = 'Found open order for {amount} shares in {stock}'
                log.info(message.format(amount=order.amount, stock=stock))

def log_open_orders():
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        for order in orders:
            message = 'Found open order for {amount} shares in {stock}'
            log.info(message.format(amount=order.amount, stock=stock))

def cancel_open_order(StockToCancel):
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        if stock == StockToCancel:
            for order in orders:
                #message = 'Canceling order of {amount} shares in {stock}'
                #log.info(message.format(amount=order.amount, stock=stock))
                cancel_order(order)
def cancel_open_orders():
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        for order in orders:
            #message = 'Canceling order of {amount} shares in {stock}'
            #log.info(message.format(amount=order.amount, stock=stock))
            cancel_order(order)

#Stop waiting
def StopWait(context, data):
    #The idea is to start fresh
    portfolio_value=context.portfolio.portfolio_value
    context.PV=portfolio_value
    context.Wait=False

# This is the every minute stuff
def handle_data(context, data):
    if context.WaitMin==0:
        context.WaitMin=context.StartingWaitMin

        GetOutFactor=1.25
        cash=context.portfolio.cash
        portfolio_value=context.portfolio.portfolio_value
        if portfolio_value < context.PV*.985 and context.account.leverage>=.33:
            context.Wait=True
            for stock in context.portfolio.positions:
                if data.can_trade(stock):
                    Curr_P = float(data.current([stock], 'price'))
                    if get_open_orders(stock):
                        continue #do NOT do anything new with this stock until the orders are filled or cancelled at end of day
                    if context.NextDay:
                        order_target_percent(stock, 0, style=LimitOrder(Curr_P*GetOutFactor))
            #context.GIWeight=.40
            context.GIWeight=1.00
        else:
            if portfolio_value > context.PV:
                context.PV=portfolio_value
            context.Wait=False
            #context.GIWeight+=.0006
            context.GIWeight=1.00

        # Maybe Take Profit
        if context.NextDay:
            for stock in context.portfolio.positions:
                if data.can_trade(stock):
                    Curr_P = float(data.current([stock], 'price'))
                    if context.portfolio.positions[stock].cost_basis*1.25<Curr_P:
                        if data.can_trade(stock):
                            if get_open_orders(stock):
                                cancel_open_order(stock)
                            order_target_percent(stock, 0, style=LimitOrder(Curr_P*.95))

        if not context.Wait and context.NextDay:

            # rebalance if no shares owned or if significant cash available
            if not context.portfolio.positions or (cash >= .25 * portfolio_value) :
                my_rebalance(context, data)

    if context.GIWeight < .40:
        context.GIWeight=.40
    if context.GIWeight > .66:
        context.GIWeight=.66
    context.GIWeight=1.00
    context.SSWeight=1-context.GIWeight

    context.WaitMin-=1
    if context.WaitMin<=0:
        context.WaitMin=0
There was a runtime error.

The price filter seemed to be broken. It is fixed now, as far as I know.
I am live trading this version.

Clone Algorithm
687
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.pipeline import Pipeline
from quantopian.algorithm import attach_pipeline, pipeline_output
from quantopian.pipeline.data.builtin import USEquityPricing
from quantopian.pipeline.data import morningstar
from quantopian.pipeline.factors import SimpleMovingAverage, AverageDollarVolume
from quantopian.pipeline.filters.morningstar import IsPrimaryShare

def initialize(context):
    #set_commission(commission.PerShare(cost=0.01, min_trade_cost=1.50))
    set_slippage(slippage.VolumeShareSlippage(volume_limit=.20, price_impact=0.0))
    #set_slippage(slippage.FixedSlippage(spread=0.00))
    set_commission(commission.PerTrade(cost=0.00))
    #set_slippage(slippage.FixedSlippage(spread=0.00))
    set_long_only()

    context.PV=context.portfolio.portfolio_value
    context.NextDay=True
    context.Wait=False
    context.StartingWaitMin=50
    context.WaitMin=context.StartingWaitMin
    #context.GIWeight=.66
    context.GIWeight=1.00
    #context.SSWeight=.34
    context.SSWeight=0

    schedule_function(StopWait, date_rules.month_start(days_offset=10), time_rules.market_open(hours=0, minutes=7))

    # Record variables at the end of each day.
    schedule_function(my_record_vars, date_rules.every_day(), time_rules.market_close())

    # Create our pipeline and attach it to our algorithm.
    my_pipe = make_pipeline(context)
    attach_pipeline(my_pipe, 'my_pipeline')

def make_pipeline(context):
    """
    Create our pipeline.
    """

    # Filter for primary share equities. IsPrimaryShare is a built-in filter.
    primary_share = IsPrimaryShare()

    # Equities listed as common stock (as opposed to, say, preferred stock).
    # 'ST00000001' indicates common stock.
    common_stock = morningstar.share_class_reference.security_type.latest.eq('ST00000001')

    # Non-depositary receipts. Recall that the ~ operator inverts filters,
    # turning Trues into Falses and vice versa
    not_depositary = ~morningstar.share_class_reference.is_depositary_receipt.latest

    # Equities not trading over-the-counter.
    not_otc = ~morningstar.share_class_reference.exchange_id.latest.startswith('OTC')

    # Not when-issued equities.
    not_wi = ~morningstar.share_class_reference.symbol.latest.endswith('.WI')

    # Equities without LP in their name, .matches does a match using a regular
    # expression
    not_lp_name = ~morningstar.company_reference.standard_name.latest.matches('.* L[. ]?P.?$')

    # Equities with a null value in the limited_partnership Morningstar
    # fundamental field.
    not_lp_balance_sheet = morningstar.balance_sheet.limited_partnership.latest.isnull()

    # Equities whose most recent Morningstar market cap is not null have
    # fundamental data and therefore are not ETFs.
    have_market_cap = morningstar.valuation.market_cap.latest.notnull()

    # At least a certain price
    price = USEquityPricing.close.latest
    AtLeastPrice   = (price >= .80)
    AtMostPrice    = (price <= 3.00)

    # Filter for stocks that pass all of our previous filters.
    tradeable_stocks = (
        primary_share
        & common_stock
        & not_depositary
        & not_otc
        & not_wi
        & not_lp_name
        & not_lp_balance_sheet
        & have_market_cap
        & AtLeastPrice
        & AtMostPrice
    )

    BottomVar=10
    TopVar=10

    LowVar=6
    HighVar=40

    log.info('\nAlgorithm initialized variables:\n BottomVar %s \n TopVar %s \n LowVar %s \n HighVar %s'
        % (BottomVar, TopVar, LowVar, HighVar)
    )
    #record(BottomVar=BottomVar, TopVar=TopVar, LowVar=LowVar, HighVar=HighVar)

    # High dollar volume filter.
    base_universe = AverageDollarVolume(
        window_length=20,
        mask=tradeable_stocks
    ).percentile_between(LowVar, HighVar)

    # Short close price average.
    ShortAvg = SimpleMovingAverage(
        inputs=[USEquityPricing.close],
        window_length=3,
        mask=base_universe
    )

    # Long close price average.
    LongAvg = SimpleMovingAverage(
        inputs=[USEquityPricing.close],
        window_length=45,
        mask=base_universe
    )

    percent_difference = (ShortAvg - LongAvg) / LongAvg

    # Filter to select securities to long.
    stocks_worst = percent_difference.bottom(BottomVar)
    stocks_best = percent_difference.top(TopVar)
    securities_to_trade = (stocks_worst | stocks_best)

    return Pipeline(
        columns={
            'stocks_worst': stocks_worst,
            'stocks_best': stocks_best
        },
        screen=(securities_to_trade),
    )

def my_compute_weights(context):
    """
    Compute ordering weights.
    """
    # Compute even target weights for our long positions and short positions.
    stocks_worst_weight = context.GIWeight / len(context.stocks_worst)
    stocks_best_weight = context.SSWeight / len(context.stocks_best)

    return stocks_worst_weight, stocks_best_weight

def before_trading_start(context, data):
    context.NextDay=True

    # Gets our pipeline output every day.
    context.output = pipeline_output('my_pipeline')

    context.stocks_worst = context.output[context.output['stocks_worst']].index.tolist()
    context.stocks_best = context.output[context.output['stocks_best']].index.tolist()

    context.stocks_worst_weight, context.stocks_best_weight = my_compute_weights(context)
    pass

def my_rebalance(context, data):
    GetInFactor=.94
    SSFactor=1.06
    if context.NextDay:

        cash=context.portfolio.cash
        log.info('\n%s   Probable cash balance BEFORE rebalancing buys' % (cash))

        for stock in context.stocks_worst:
            if data.can_trade(stock):
                Curr_P = float(data.current([stock], 'price'))
                if get_open_orders(stock):
                    #log_open_order(stock)
                    continue #do NOT do anything new with this stock until the orders are filled or cancelled at end of day
                if cash >= context.stocks_worst_weight*context.portfolio.portfolio_value:
                    order_value(stock, context.stocks_worst_weight*context.portfolio.portfolio_value,
                        style=LimitOrder(Curr_P*GetInFactor)
                    )
                    cash=cash - (context.stocks_worst_weight*context.portfolio.portfolio_value)

        for stock in context.stocks_best:
            if data.can_trade(stock):
                Curr_P = float(data.current([stock], 'price'))
                if get_open_orders(stock):
                    #log_open_order(stock)
                    continue #do NOT do anything new with this stock until the orders are filled or cancelled at end of day
                if cash >= context.stocks_best_weight*context.portfolio.portfolio_value:
                    order_value(stock, -context.stocks_best_weight*context.portfolio.portfolio_value,
                        style=LimitOrder(Curr_P*SSFactor)
                    )
                    cash=cash - (context.stocks_best_weight*context.portfolio.portfolio_value)

        log.info('\n%s   Probable cash balance AFTER buys and BEFORE sells' % (cash))

        for stock in context.portfolio.positions:
            if stock not in context.stocks_worst and stock not in context.stocks_best and data.can_trade(stock):
                if get_open_orders(stock):
                    continue #do NOT do anything new with this stock until the orders are filled or cancelled at end of day
                StockShares = context.portfolio.positions[stock].amount
                Curr_P = float(data.current([stock], 'price'))
                order(stock, -StockShares,
                    style=LimitOrder(Curr_P)
                )
                #log.info('\nSELLING   %s   shares of   %s' % (StockSharesToSellNow, stock))

        context.NextDay=False

def my_record_vars(context, data):
    """
    Record variables at the end of each day.
    """

    # Record our variables.
    record(MaxPV=context.PV/context.portfolio.starting_cash, leverage=context.account.leverage)
    longs = shorts = 0
    for position in context.portfolio.positions.itervalues():
        if position.amount > 0:
            longs += 1
        if position.amount < 0:
            shorts += 1
    record(long_count=longs, short_count=shorts)


def log_open_order(StockToLog):
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        if stock == StockToLog:
            for order in orders:
                message = 'Found open order for {amount} shares in {stock}'
                log.info(message.format(amount=order.amount, stock=stock))

def log_open_orders():
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        for order in orders:
            message = 'Found open order for {amount} shares in {stock}'
            log.info(message.format(amount=order.amount, stock=stock))

def cancel_open_order(StockToCancel):
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        if stock == StockToCancel:
            for order in orders:
                #message = 'Canceling order of {amount} shares in {stock}'
                #log.info(message.format(amount=order.amount, stock=stock))
                cancel_order(order)
def cancel_open_orders():
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        for order in orders:
            #message = 'Canceling order of {amount} shares in {stock}'
            #log.info(message.format(amount=order.amount, stock=stock))
            cancel_order(order)

#Stop waiting
def StopWait(context, data):
    #The idea is to start fresh
    portfolio_value=context.portfolio.portfolio_value
    context.PV=portfolio_value
    context.Wait=False

# This is the every minute stuff
def handle_data(context, data):
    if context.WaitMin==0:
        context.WaitMin=context.StartingWaitMin

        GetOutFactor=1.25
        cash=context.portfolio.cash
        portfolio_value=context.portfolio.portfolio_value
        if portfolio_value < context.PV*.985 and context.account.leverage>=.33:
            context.Wait=True
            for stock in context.portfolio.positions:
                if data.can_trade(stock):
                    Curr_P = float(data.current([stock], 'price'))
                    if get_open_orders(stock):
                        continue #do NOT do anything new with this stock until the orders are filled or cancelled at end of day
                    if context.NextDay:
                        order_target_percent(stock, 0, style=LimitOrder(Curr_P*GetOutFactor))
            #context.GIWeight=.40
            context.GIWeight=1.00
        else:
            if portfolio_value > context.PV:
                context.PV=portfolio_value
            context.Wait=False
            #context.GIWeight+=.0006
            context.GIWeight=1.00

        # Maybe Take Profit
        if context.NextDay:
            for stock in context.portfolio.positions:
                if data.can_trade(stock):
                    Curr_P = float(data.current([stock], 'price'))
                    if context.portfolio.positions[stock].cost_basis*1.25<Curr_P:
                        if data.can_trade(stock):
                            if get_open_orders(stock):
                                cancel_open_order(stock)
                            order_target_percent(stock, 0, style=LimitOrder(Curr_P*.95))

        if not context.Wait and context.NextDay:

            # rebalance if no shares owned or if significant cash available
            if not context.portfolio.positions or (cash >= .25 * portfolio_value) :
                my_rebalance(context, data)

    if context.GIWeight < .40:
        context.GIWeight=.40
    if context.GIWeight > .66:
        context.GIWeight=.66
    context.GIWeight=1.00
    context.SSWeight=1-context.GIWeight

    context.WaitMin-=1
    if context.WaitMin<=0:
        context.WaitMin=0
There was a runtime error.

I haven't looked at the code itself, but why does the leverage stay so low?

Because of my method of tracking available cash. Unless 100% of placed orders are executed, we will never have 1.00 leverage.
Because the algo appears to be profitable in spite of this characteristic, I left the behavior in place, because I like cash.
I could get the money out faster for a small emergency if needed.

Live Trading Robinhood real money "Robin Hood Throws A Party"
Started Trading: market open Tuesday, 9/20/2016
Capital base: $1,583.82

As of market close Friday, 9/23/2016
2.80% Returns / 1.70% Backtest / 1.10% Benchmark
$44.29 Dollar P/L 23.14 Sharpe $669.05 Long Exposure $959.05 Available Cash

Saturday, 9/24/2016 deposited $1,000 Stopped / Started algorithm $1,959.05 Available Cash

A lot of clones but no comments. Let me know if any of y'all become millionaires.

I'm hoping for a stellar week obviously. Could end up being a disappointing drawdown.

Are there still issues with delisted stocks on the latest algo?

Short answer, yes.
Longer answer, less likely because of the universe bottom price limit of $.80. Also, the volume universe bottom variable is at 6% instead of 1% now. That should also reduce the likelihood of delistings.

These changes do tend to trim the profits. Of course, so do those #&@!#@! delistings!

Are you not having the problem where the order does not get placed around market open? The order will only get placed if I make manual changes to my portfolio (buy/sell some of the shares), as if my manual changes "trigger" the algorithm. So this means if I dont make any manual changes, there will be no orders placed whatsoever. If I make changes at market open, the orders will get placed around 10:30; if I make changes at 1:00PM, orders will get placed around 1:20~30PM.

Do you not have this problem?

You may need to customize the algo to fit your situation and / or preferences.

If you have 25% or more cash, then it will rebalance if 50 minutes has passed since the algo started warming up for the trading day. That time that it starts warming up seems to vary, based on the time that the orders are placed. The rebalance will not do anything for a particular stock if an order already exists. The exception is the Take Profit code will cancel an existing order in order to try to sell.

Every 50 minutes, it will check to see if it should try to sell either to Get Out or to Take Profit.

What do you mean by "warming up"? does that mean my manual changes to my portfolio triggers the "warming up"? Shouldn't this behavior be automatic? I have more than 25% cash. usually have 50% left to use

What do you mean by "warming up"? does that mean my manual changes to my portfolio triggers the "warming up"? Shouldn't this behavior be automatic? I have more than 25% cash. usually have 50% left to use

When you manually stop / start the algo, it says something like, "warming up" I think. At market open or some number of minutes before, the algo starts up automatically. It is not the algo doing it, it is Quantopian that starts up each algo sometime each day, shortly before market open. It is probably more accurate to say, that the before trading day function gets executed. Because all the previous day's unfilled orders were canceled at market close, then it is very likely to place orders at sometime between market open and 50 minutes later.

You can lock down the algo to rebalance at specific time with the schedule function in initialize function. For some reason, I seem to get better returns the way it is now in my algo. Feel free to experiment until it behaves the way you want it to.

do you think the reason why I am having to do manual transactions before the algo kicks in each day is because I have ~40% of my portfolio invested in my own investments (non-algo purchases)? I have a feeling that may be the reason, so I might try making a new robinhood account for just algo. I will get back to you on this

That is a good idea. A great big reason is, the algo will treat your other positions as if they belong to the algo. When it rebalances, It will attempt to sell your other positions at current price if the stock is not in our filtered pipeline provided list of stocks.

Hi Charles,

What's the logic behind your Algo?

Live Trading Robinhood real money "Robin Hood Throws A Party"
Started Trading: Saturday, 9/24/2016, 7:05:40 PM
Capital base: $2,632.71

As of market close Thursday, 9/29/2016
0.65% Returns / 1.00% Backtest thru 9/28/2016 / -0.60% Benchmark
$17.12 Dollar P/L 4.91 Sharpe $1,742.08 Long Exposure $907.75 Available Cash

Thursday, 9/29/2016 deposited $1,000 Stopped / Started algorithm
$3,815.50 Available Cash now using Robinhood Gold $2,000 / was using Robinhood Instant

Yourness,
basically low volume stocks can be profitable for various reasons, but it does have risks, such as liquidity risk and risk of delisting. Use with caution.

I accidentally was live trading with an experimental version
So I did a stop / start of my algo.

I also ended up making certain significant changes to my algo.
Now, it attempts to use all the buying power. Robinhood for various reasons rejects many trades, but at least now, it does attempt to place orders to use all available money.

If you are not using Robinhood Gold, then make sure you set
context.UseRobinhoodGold=False
in initialize.

Clone Algorithm
687
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.pipeline import Pipeline
from quantopian.algorithm import attach_pipeline, pipeline_output
from quantopian.pipeline.data.builtin import USEquityPricing
from quantopian.pipeline.data import morningstar
from quantopian.pipeline.factors import SimpleMovingAverage, AverageDollarVolume
from quantopian.pipeline.filters.morningstar import IsPrimaryShare

def initialize(context):
    #set_commission(commission.PerShare(cost=0.01, min_trade_cost=1.50))
    set_slippage(slippage.VolumeShareSlippage(volume_limit=.20, price_impact=0.0))
    #set_slippage(slippage.FixedSlippage(spread=0.00))
    set_commission(commission.PerTrade(cost=0.00))
    #set_slippage(slippage.FixedSlippage(spread=0.00))
    set_long_only()
    
    context.UseRobinhoodGold=True #Set this to False if you do not have Robinhood Gold
    context.RobinhoodGold=2000

    context.PV=context.portfolio.portfolio_value
    context.NextDay=True
    context.Wait=False
    context.StartingWaitMin=50
    context.WaitMin=context.StartingWaitMin
    #context.GIWeight=.66
    context.GIWeight=1.00
    #context.SSWeight=.34
    context.SSWeight=0

    schedule_function(StopWait, date_rules.month_start(days_offset=10), time_rules.market_open(hours=0, minutes=7))

    # Prevent excessive logging of canceled orders at market close.
    schedule_function(cancel_open_orders, date_rules.every_day(), time_rules.market_close(hours=0, minutes=7))

    # Record variables at the end of each day.
    schedule_function(my_record_vars, date_rules.every_day(), time_rules.market_close())

    # Create our pipeline and attach it to our algorithm.
    my_pipe = make_pipeline(context)
    attach_pipeline(my_pipe, 'my_pipeline')

def make_pipeline(context):
    """
    Create our pipeline.
    """

    # Filter for primary share equities. IsPrimaryShare is a built-in filter.
    primary_share = IsPrimaryShare()

    # Equities listed as common stock (as opposed to, say, preferred stock).
    # 'ST00000001' indicates common stock.
    common_stock = morningstar.share_class_reference.security_type.latest.eq('ST00000001')

    # Non-depositary receipts. Recall that the ~ operator inverts filters,
    # turning Trues into Falses and vice versa
    not_depositary = ~morningstar.share_class_reference.is_depositary_receipt.latest

    # Equities not trading over-the-counter.
    not_otc = ~morningstar.share_class_reference.exchange_id.latest.startswith('OTC')

    # Not when-issued equities.
    not_wi = ~morningstar.share_class_reference.symbol.latest.endswith('.WI')

    # Equities without LP in their name, .matches does a match using a regular
    # expression
    not_lp_name = ~morningstar.company_reference.standard_name.latest.matches('.* L[. ]?P.?$')

    # Equities with a null value in the limited_partnership Morningstar
    # fundamental field.
    not_lp_balance_sheet = morningstar.balance_sheet.limited_partnership.latest.isnull()

    # Equities whose most recent Morningstar market cap is not null have
    # fundamental data and therefore are not ETFs.
    have_market_cap = morningstar.valuation.market_cap.latest.notnull()

    # At least a certain price
    price = USEquityPricing.close.latest
    AtLeastPrice   = (price >= .80)
    AtMostPrice    = (price <= 3.00)

    # Filter for stocks that pass all of our previous filters.
    tradeable_stocks = (
        primary_share
        & common_stock
        & not_depositary
        & not_otc
        & not_wi
        & not_lp_name
        & not_lp_balance_sheet
        & have_market_cap
        & AtLeastPrice
        & AtMostPrice
    )

    BottomVar=10
    TopVar=10

    LowVar=6
    HighVar=40

    log.info('\nAlgorithm initialized variables:\n BottomVar %s \n TopVar %s \n LowVar %s \n HighVar %s'
        % (BottomVar, TopVar, LowVar, HighVar)
    )
    #record(BottomVar=BottomVar, TopVar=TopVar, LowVar=LowVar, HighVar=HighVar)

    # High dollar volume filter.
    base_universe = AverageDollarVolume(
        window_length=20,
        mask=tradeable_stocks
    ).percentile_between(LowVar, HighVar)

    # Short close price average.
    ShortAvg = SimpleMovingAverage(
        inputs=[USEquityPricing.close],
        window_length=3,
        mask=base_universe
    )

    # Long close price average.
    LongAvg = SimpleMovingAverage(
        inputs=[USEquityPricing.close],
        window_length=45,
        mask=base_universe
    )

    percent_difference = (ShortAvg - LongAvg) / LongAvg

    # Filter to select securities to long.
    stocks_worst = percent_difference.bottom(BottomVar)
    stocks_best = percent_difference.top(TopVar)
    securities_to_trade = (stocks_worst | stocks_best)

    return Pipeline(
        columns={
            'stocks_worst': stocks_worst,
            'stocks_best': stocks_best
        },
        screen=(securities_to_trade),
    )

def my_compute_weights(context):
    """
    Compute ordering weights.
    """
    # Compute even target weights for our long positions and short positions.
    stocks_worst_weight = context.GIWeight / len(context.stocks_worst)
    stocks_best_weight = context.SSWeight / len(context.stocks_best)

    return stocks_worst_weight, stocks_best_weight

def before_trading_start(context, data):
    context.NextDay=True

    # Gets our pipeline output every day.
    context.output = pipeline_output('my_pipeline')

    context.stocks_worst = context.output[context.output['stocks_worst']].index.tolist()
    context.stocks_best = context.output[context.output['stocks_best']].index.tolist()

    context.stocks_worst_weight, context.stocks_best_weight = my_compute_weights(context)
    pass

def my_rebalance(context, data):
    GetInFactor=.94
    if context.NextDay:
        cancel_open_orders(context, data)

        cash=context.portfolio.cash
        if context.UseRobinhoodGold:
            if cash >= context.RobinhoodGold:
                cash += context.RobinhoodGold
            else:
                cash *= 2

        for stock in context.portfolio.positions:
            if stock not in context.stocks_worst and stock not in context.stocks_best and data.can_trade(stock):
                StockShares = context.portfolio.positions[stock].amount
                Curr_P = float(data.current([stock], 'price'))
                StockSharesValue = StockShares * Curr_P
                order(stock, -StockShares,
                    style=LimitOrder(Curr_P)
                )
                #log.info('\nSELLING   %s   shares of   %s' % (StockSharesToSellNow, stock))
                cash += StockSharesValue

        log.info('\n%s   Probable cash balance AFTER rebalancing sells' % (cash))

        while cash >= 10:
            for stock in context.stocks_worst:
                if data.can_trade(stock):
                    Curr_P = float(data.current([stock], 'price'))
                    order_value(stock, context.stocks_worst_weight*cash,
                        style=LimitOrder(Curr_P*GetInFactor)
                    )
                    cash = cash - (context.stocks_worst_weight*cash)

        log.info('\n%s   Probable cash balance AFTER rebalancing buys' % (cash))

        context.NextDay=False

def my_record_vars(context, data):
    """
    Record variables at the end of each day.
    """

    # Record our variables.
    record(MaxPV=context.PV/context.portfolio.starting_cash, leverage=context.account.leverage)
    longs = shorts = 0
    for position in context.portfolio.positions.itervalues():
        if position.amount > 0:
            longs += 1
        if position.amount < 0:
            shorts += 1
    record(long_count=longs, short_count=shorts)


def log_open_order(StockToLog):
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        if stock == StockToLog:
            for order in orders:
                message = 'Found open order for {amount} shares in {stock}'
                log.info(message.format(amount=order.amount, stock=stock))

def log_open_orders():
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        for order in orders:
            message = 'Found open order for {amount} shares in {stock}'
            log.info(message.format(amount=order.amount, stock=stock))

def cancel_open_order(StockToCancel):
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        if stock == StockToCancel:
            for order in orders:
                #message = 'Canceling order of {amount} shares in {stock}'
                #log.info(message.format(amount=order.amount, stock=stock))
                cancel_order(order)
def cancel_open_orders(context, data):
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        for order in orders:
            #message = 'Canceling order of {amount} shares in {stock}'
            #log.info(message.format(amount=order.amount, stock=stock))
            cancel_order(order)

#Stop waiting
def StopWait(context, data):
    #The idea is to start fresh
    portfolio_value=context.portfolio.portfolio_value
    context.PV=portfolio_value
    context.Wait=False

# This is the every minute stuff
def handle_data(context, data):
    # Maybe Take Profit
    if context.NextDay:
        for stock in context.portfolio.positions:
            if data.can_trade(stock):
                Curr_P = float(data.current([stock], 'price'))
                if context.portfolio.positions[stock].cost_basis*1.25<Curr_P:
                    if data.can_trade(stock):
                        if get_open_orders(stock):
                            cancel_open_order(stock)
                        order_target_percent(stock, 0, style=LimitOrder(Curr_P*.95))

    if context.WaitMin==0:
        if context.NextDay:
            my_rebalance(context, data)

        context.WaitMin=context.StartingWaitMin

        GetOutFactor=1.25
        portfolio_value=context.portfolio.portfolio_value
        if portfolio_value < context.PV*.985 and context.account.leverage>=.33:
            context.Wait=True
            for stock in context.portfolio.positions:
                if data.can_trade(stock):
                    Curr_P = float(data.current([stock], 'price'))
                    if get_open_orders(stock):
                        continue #do NOT do anything new with this stock until the orders are filled or cancelled at end of day
                    if context.NextDay:
                        order_target_percent(stock, 0, style=LimitOrder(Curr_P*GetOutFactor))
            #context.GIWeight=.40
            context.GIWeight=1.00
        else:
            if portfolio_value > context.PV:
                context.PV=portfolio_value
            context.Wait=False
            #context.GIWeight+=.0006
            context.GIWeight=1.00

    if context.GIWeight < .40:
        context.GIWeight=.40
    if context.GIWeight > .66:
        context.GIWeight=.66
    context.GIWeight=1.00
    context.SSWeight=1-context.GIWeight

    context.WaitMin-=1
    if context.WaitMin<=0:
        context.WaitMin=0
There was a runtime error.

Can it be trade in IB? What's the difference in code Robinhood vs IB?

Thank you for sharing your work. It is very, very generous of you. I have been captivated by this algo all weekend long. I have tried many tweaks, dollar amounts, etc. The results are incredible. I'm deploying it live next week to test.

With gratitude - R

Your welcome. Just be careful. So far, it seems like the live trading is always worse results than back testing. This particular version so far does appear to be profitable. Need more time to prove it though. I think there will always be at least some risk of stocks delisting though. The $0.80 bottom limit seems to help with that problem. However, I've read and heard others say that $3.00 is necessary to nearly eliminate the delisting risk.

This version does seem way less likely to ever day trade, because of the 25% take profit instead of the previous 12.5% take profit.

Live Trading Robinhood real money
Started Trading: Friday, 9/30/2016, 1:10:01 PM
Capital base: $3,587.30

As of market close Wednesday, 10/05/2016
1.79% Returns / approx 4.50% Backtest / -0.50% Benchmark
$64.32 Dollar P/L 3.88 Sharpe $2,429.83 Long Exposure $1,221.79 Available Cash

Wednesday, 10/05/2016 after market close, stop / start algorithm
new version of algorithm is nicknamed Robin Hood Plays Twister

If you are worried about day trading, then make sure you have pattern day trade protection enabled for your broker.
Robinhood has that and I heard someone else say IB has it too.

This version spreads the risk a little better among the pipeline stocks and does more but smaller trades as well. Should have fewer rejected trades.
Does reasonably well at using all available cash. Sometimes leverage approaches 1.00.

As always, use with caution.

Clone Algorithm
687
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.pipeline import Pipeline
from quantopian.algorithm import attach_pipeline, pipeline_output
from quantopian.pipeline.data.builtin import USEquityPricing
from quantopian.pipeline.data import morningstar
from quantopian.pipeline.factors import SimpleMovingAverage, AverageDollarVolume
from quantopian.pipeline.filters.morningstar import IsPrimaryShare

def initialize(context):
    #set_commission(commission.PerShare(cost=0.01, min_trade_cost=1.50))
    set_slippage(slippage.VolumeShareSlippage(volume_limit=.20, price_impact=0.0))
    #set_slippage(slippage.FixedSlippage(spread=0.00))
    set_commission(commission.PerTrade(cost=0.00))
    #set_slippage(slippage.FixedSlippage(spread=0.00))
    set_long_only()
    
    context.MyLeastPrice=0.80
    context.MyMostPrice=3.00
    context.MaxPositionValue=context.portfolio.portfolio_value*.20
    
    # Rebalance
    EveryThisManyMinutes=50
    for minutez in xrange(5, 385, EveryThisManyMinutes):
        schedule_function(my_rebalance, date_rules.every_day(), time_rules.market_open(minutes=minutez))

    # Prevent excessive logging of canceled orders at market close.
    schedule_function(cancel_open_orders, date_rules.every_day(), time_rules.market_close(hours=0, minutes=1))

    # Record variables at the end of each day.
    schedule_function(my_record_vars, date_rules.every_day(), time_rules.market_close())

    # Create our pipeline and attach it to our algorithm.
    my_pipe = make_pipeline(context)
    attach_pipeline(my_pipe, 'my_pipeline')

def make_pipeline(context):
    """
    Create our pipeline.
    """

    # Filter for primary share equities. IsPrimaryShare is a built-in filter.
    primary_share = IsPrimaryShare()

    # Equities listed as common stock (as opposed to, say, preferred stock).
    # 'ST00000001' indicates common stock.
    common_stock = morningstar.share_class_reference.security_type.latest.eq('ST00000001')

    # Non-depositary receipts. Recall that the ~ operator inverts filters,
    # turning Trues into Falses and vice versa
    not_depositary = ~morningstar.share_class_reference.is_depositary_receipt.latest

    # Equities not trading over-the-counter.
    not_otc = ~morningstar.share_class_reference.exchange_id.latest.startswith('OTC')

    # Not when-issued equities.
    not_wi = ~morningstar.share_class_reference.symbol.latest.endswith('.WI')

    # Equities without LP in their name, .matches does a match using a regular
    # expression
    not_lp_name = ~morningstar.company_reference.standard_name.latest.matches('.* L[. ]?P.?$')

    # Equities with a null value in the limited_partnership Morningstar
    # fundamental field.
    not_lp_balance_sheet = morningstar.balance_sheet.limited_partnership.latest.isnull()

    # Equities whose most recent Morningstar market cap is not null have
    # fundamental data and therefore are not ETFs.
    have_market_cap = morningstar.valuation.market_cap.latest.notnull()

    # At least a certain price
    price = USEquityPricing.close.latest
    AtLeastPrice   = (price >= context.MyLeastPrice)
    AtMostPrice    = (price <= context.MyMostPrice)

    # Filter for stocks that pass all of our previous filters.
    tradeable_stocks = (
        primary_share
        & common_stock
        & not_depositary
        & not_otc
        & not_wi
        & not_lp_name
        & not_lp_balance_sheet
        & have_market_cap
        & AtLeastPrice
        & AtMostPrice
    )

    BottomVar=10
    LowVar=6
    HighVar=40

    log.info('\nAlgorithm initialized variables:\n BottomVar %s \n LowVar %s \n HighVar %s'
        % (BottomVar, LowVar, HighVar)
    )

    # High dollar volume filter.
    base_universe = AverageDollarVolume(
        window_length=20,
        mask=tradeable_stocks
    ).percentile_between(LowVar, HighVar)

    # Short close price average.
    ShortAvg = SimpleMovingAverage(
        inputs=[USEquityPricing.close],
        window_length=3,
        mask=base_universe
    )

    # Long close price average.
    LongAvg = SimpleMovingAverage(
        inputs=[USEquityPricing.close],
        window_length=45,
        mask=base_universe
    )

    percent_difference = (ShortAvg - LongAvg) / LongAvg

    # Filter to select securities to long.
    stocks_worst = percent_difference.bottom(BottomVar)
    securities_to_trade = (stocks_worst)

    return Pipeline(
        columns={
            'stocks_worst': stocks_worst
        },
        screen=(securities_to_trade),
    )

def my_compute_weights(context):
    """
    Compute ordering weights.
    """
    # Compute even target weights for our long positions and short positions.
    stocks_worst_weight = 1.00/len(context.stocks_worst)

    return stocks_worst_weight

def before_trading_start(context, data):
    # Gets our pipeline output every day.
    context.output = pipeline_output('my_pipeline')

    context.stocks_worst = context.output[context.output['stocks_worst']].index.tolist()

    context.stocks_worst_weight = my_compute_weights(context)
    pass

def my_rebalance(context, data):
    TakeProfitFactor=1.10
    GetOutFactor=.95
    GetInFactor=.97

    cash=context.portfolio.cash

    # Maybe Take Profit or Get Out because no longer in pipeline
    for stock in context.portfolio.positions:
        if data.can_trade(stock):
            Curr_P = float(data.current([stock], 'price'))
            if (
                Curr_P>context.portfolio.positions[stock].cost_basis*TakeProfitFactor
                or
                stock not in context.stocks_worst
            ):
                if get_open_orders(stock):
                    cancel_open_order(stock)
                StockShares = context.portfolio.positions[stock].amount
                StockSharesValue = StockShares * Curr_P
                order(stock, -StockShares,
                    style=LimitOrder(Curr_P*GetOutFactor)
                )
                cash += StockSharesValue

    if cash >= 10:
        for stock in context.stocks_worst:
            if data.can_trade(stock):
                Curr_P = float(data.current([stock], 'price'))
                if Curr_P>=context.MyLeastPrice+0.10:
                    StockShares = context.stocks_worst_weight*cash/Curr_P/76*10
                    if StockShares<1:
                        StockShares=1
                    if context.MaxPositionValue>StockShares*Curr_P:
                        order(stock, StockShares,
                            style=LimitOrder(Curr_P*GetInFactor)
                        )

def my_record_vars(context, data):
    """
    Record variables at the end of each day.
    """

    # Record our variables.
    record(leverage=context.account.leverage)
    longs = shorts = 0
    for position in context.portfolio.positions.itervalues():
        if position.amount > 0:
            longs += 1
        if position.amount < 0:
            shorts += 1
    record(long_count=longs, short_count=shorts)


def log_open_order(StockToLog):
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        if stock == StockToLog:
            for order in orders:
                message = 'Found open order for {amount} shares in {stock}'
                log.info(message.format(amount=order.amount, stock=stock))

def log_open_orders():
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        for order in orders:
            message = 'Found open order for {amount} shares in {stock}'
            log.info(message.format(amount=order.amount, stock=stock))

def cancel_open_order(StockToCancel):
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        if stock == StockToCancel:
            for order in orders:
                #message = 'Canceling order of {amount} shares in {stock}'
                #log.info(message.format(amount=order.amount, stock=stock))
                cancel_order(order)
def cancel_open_orders(context, data):
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        for order in orders:
            #message = 'Canceling order of {amount} shares in {stock}'
            #log.info(message.format(amount=order.amount, stock=stock))
            cancel_order(order)

# This is the every minute stuff
def handle_data(context, data):
    pass
There was a runtime error.

Sorry, this is the version I meant to post. The only change is 5 minute between rebalancing instead of 50 minutes.

Clone Algorithm
173
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.pipeline import Pipeline
from quantopian.algorithm import attach_pipeline, pipeline_output
from quantopian.pipeline.data.builtin import USEquityPricing
from quantopian.pipeline.data import morningstar
from quantopian.pipeline.factors import SimpleMovingAverage, AverageDollarVolume
from quantopian.pipeline.filters.morningstar import IsPrimaryShare

def initialize(context):
    #set_commission(commission.PerShare(cost=0.01, min_trade_cost=1.50))
    set_slippage(slippage.VolumeShareSlippage(volume_limit=.20, price_impact=0.0))
    #set_slippage(slippage.FixedSlippage(spread=0.00))
    set_commission(commission.PerTrade(cost=0.00))
    #set_slippage(slippage.FixedSlippage(spread=0.00))
    set_long_only()
    
    context.MyLeastPrice=0.80
    context.MyMostPrice=3.00
    context.MaxPositionValue=context.portfolio.portfolio_value*.20
    
    # Rebalance
    EveryThisManyMinutes=5
    for minutez in xrange(5, 385, EveryThisManyMinutes):
        schedule_function(my_rebalance, date_rules.every_day(), time_rules.market_open(minutes=minutez))

    # Prevent excessive logging of canceled orders at market close.
    schedule_function(cancel_open_orders, date_rules.every_day(), time_rules.market_close(hours=0, minutes=1))

    # Record variables at the end of each day.
    schedule_function(my_record_vars, date_rules.every_day(), time_rules.market_close())

    # Create our pipeline and attach it to our algorithm.
    my_pipe = make_pipeline(context)
    attach_pipeline(my_pipe, 'my_pipeline')

def make_pipeline(context):
    """
    Create our pipeline.
    """

    # Filter for primary share equities. IsPrimaryShare is a built-in filter.
    primary_share = IsPrimaryShare()

    # Equities listed as common stock (as opposed to, say, preferred stock).
    # 'ST00000001' indicates common stock.
    common_stock = morningstar.share_class_reference.security_type.latest.eq('ST00000001')

    # Non-depositary receipts. Recall that the ~ operator inverts filters,
    # turning Trues into Falses and vice versa
    not_depositary = ~morningstar.share_class_reference.is_depositary_receipt.latest

    # Equities not trading over-the-counter.
    not_otc = ~morningstar.share_class_reference.exchange_id.latest.startswith('OTC')

    # Not when-issued equities.
    not_wi = ~morningstar.share_class_reference.symbol.latest.endswith('.WI')

    # Equities without LP in their name, .matches does a match using a regular
    # expression
    not_lp_name = ~morningstar.company_reference.standard_name.latest.matches('.* L[. ]?P.?$')

    # Equities with a null value in the limited_partnership Morningstar
    # fundamental field.
    not_lp_balance_sheet = morningstar.balance_sheet.limited_partnership.latest.isnull()

    # Equities whose most recent Morningstar market cap is not null have
    # fundamental data and therefore are not ETFs.
    have_market_cap = morningstar.valuation.market_cap.latest.notnull()

    # At least a certain price
    price = USEquityPricing.close.latest
    AtLeastPrice   = (price >= context.MyLeastPrice)
    AtMostPrice    = (price <= context.MyMostPrice)

    # Filter for stocks that pass all of our previous filters.
    tradeable_stocks = (
        primary_share
        & common_stock
        & not_depositary
        & not_otc
        & not_wi
        & not_lp_name
        & not_lp_balance_sheet
        & have_market_cap
        & AtLeastPrice
        & AtMostPrice
    )

    BottomVar=10
    LowVar=6
    HighVar=40

    log.info('\nAlgorithm initialized variables:\n BottomVar %s \n LowVar %s \n HighVar %s'
        % (BottomVar, LowVar, HighVar)
    )

    # High dollar volume filter.
    base_universe = AverageDollarVolume(
        window_length=20,
        mask=tradeable_stocks
    ).percentile_between(LowVar, HighVar)

    # Short close price average.
    ShortAvg = SimpleMovingAverage(
        inputs=[USEquityPricing.close],
        window_length=3,
        mask=base_universe
    )

    # Long close price average.
    LongAvg = SimpleMovingAverage(
        inputs=[USEquityPricing.close],
        window_length=45,
        mask=base_universe
    )

    percent_difference = (ShortAvg - LongAvg) / LongAvg

    # Filter to select securities to long.
    stocks_worst = percent_difference.bottom(BottomVar)
    securities_to_trade = (stocks_worst)

    return Pipeline(
        columns={
            'stocks_worst': stocks_worst
        },
        screen=(securities_to_trade),
    )

def my_compute_weights(context):
    """
    Compute ordering weights.
    """
    # Compute even target weights for our long positions and short positions.
    stocks_worst_weight = 1.00/len(context.stocks_worst)

    return stocks_worst_weight

def before_trading_start(context, data):
    # Gets our pipeline output every day.
    context.output = pipeline_output('my_pipeline')

    context.stocks_worst = context.output[context.output['stocks_worst']].index.tolist()

    context.stocks_worst_weight = my_compute_weights(context)
    pass

def my_rebalance(context, data):
    TakeProfitFactor=1.10
    GetOutFactor=.95
    GetInFactor=.97

    cash=context.portfolio.cash

    # Maybe Take Profit or Get Out because no longer in pipeline
    for stock in context.portfolio.positions:
        if data.can_trade(stock):
            Curr_P = float(data.current([stock], 'price'))
            if (
                Curr_P>context.portfolio.positions[stock].cost_basis*TakeProfitFactor
                or
                stock not in context.stocks_worst
            ):
                if get_open_orders(stock):
                    cancel_open_order(stock)
                StockShares = context.portfolio.positions[stock].amount
                StockSharesValue = StockShares * Curr_P
                order(stock, -StockShares,
                    style=LimitOrder(Curr_P*GetOutFactor)
                )
                cash += StockSharesValue

    if cash >= 10:
        for stock in context.stocks_worst:
            if data.can_trade(stock):
                Curr_P = float(data.current([stock], 'price'))
                if Curr_P>=context.MyLeastPrice+0.10:
                    StockShares = context.stocks_worst_weight*cash/Curr_P/76*10
                    if StockShares<1:
                        StockShares=1
                    if context.MaxPositionValue>StockShares*Curr_P:
                        order(stock, StockShares,
                            style=LimitOrder(Curr_P*GetInFactor)
                        )

def my_record_vars(context, data):
    """
    Record variables at the end of each day.
    """

    # Record our variables.
    record(leverage=context.account.leverage)
    longs = shorts = 0
    for position in context.portfolio.positions.itervalues():
        if position.amount > 0:
            longs += 1
        if position.amount < 0:
            shorts += 1
    record(long_count=longs, short_count=shorts)


def log_open_order(StockToLog):
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        if stock == StockToLog:
            for order in orders:
                message = 'Found open order for {amount} shares in {stock}'
                log.info(message.format(amount=order.amount, stock=stock))

def log_open_orders():
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        for order in orders:
            message = 'Found open order for {amount} shares in {stock}'
            log.info(message.format(amount=order.amount, stock=stock))

def cancel_open_order(StockToCancel):
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        if stock == StockToCancel:
            for order in orders:
                #message = 'Canceling order of {amount} shares in {stock}'
                #log.info(message.format(amount=order.amount, stock=stock))
                cancel_order(order)
def cancel_open_orders(context, data):
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        for order in orders:
            #message = 'Canceling order of {amount} shares in {stock}'
            #log.info(message.format(amount=order.amount, stock=stock))
            cancel_order(order)

# This is the every minute stuff
def handle_data(context, data):
    pass
There was a runtime error.

Sorry everybody. I found a major bug. It was the MaxPosition variables. Eventually it became so small relative to the portfolio that it did not allow more buys.

I fixed it.

Clone Algorithm
687
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.pipeline import Pipeline
from quantopian.algorithm import attach_pipeline, pipeline_output
from quantopian.pipeline.data.builtin import USEquityPricing
from quantopian.pipeline.data import morningstar
from quantopian.pipeline.factors import SimpleMovingAverage, AverageDollarVolume
from quantopian.pipeline.filters.morningstar import IsPrimaryShare

def initialize(context):
    #set_commission(commission.PerShare(cost=0.01, min_trade_cost=1.50))
    set_slippage(slippage.VolumeShareSlippage(volume_limit=.20, price_impact=0.0))
    #set_slippage(slippage.FixedSlippage(spread=0.00))
    set_commission(commission.PerTrade(cost=0.00))
    #set_slippage(slippage.FixedSlippage(spread=0.00))
    set_long_only()

    context.MyLeastPrice=0.80
    context.MyMostPrice=3.00
    context.MaxPositionFactor=0.20

    # Rebalance
    EveryThisManyMinutes=5
    for minutez in xrange(5, 385, EveryThisManyMinutes):
        schedule_function(my_rebalance, date_rules.every_day(), time_rules.market_open(minutes=minutez))

    # Prevent excessive logging of canceled orders at market close.
    schedule_function(cancel_open_orders, date_rules.every_day(), time_rules.market_close(hours=0, minutes=1))

    # Record variables at the end of each day.
    schedule_function(my_record_vars, date_rules.every_day(), time_rules.market_close())

    # Create our pipeline and attach it to our algorithm.
    my_pipe = make_pipeline(context)
    attach_pipeline(my_pipe, 'my_pipeline')

def make_pipeline(context):
    """
    Create our pipeline.
    """

    # Filter for primary share equities. IsPrimaryShare is a built-in filter.
    primary_share = IsPrimaryShare()

    # Equities listed as common stock (as opposed to, say, preferred stock).
    # 'ST00000001' indicates common stock.
    common_stock = morningstar.share_class_reference.security_type.latest.eq('ST00000001')

    # Non-depositary receipts. Recall that the ~ operator inverts filters,
    # turning Trues into Falses and vice versa
    not_depositary = ~morningstar.share_class_reference.is_depositary_receipt.latest

    # Equities not trading over-the-counter.
    not_otc = ~morningstar.share_class_reference.exchange_id.latest.startswith('OTC')

    # Not when-issued equities.
    not_wi = ~morningstar.share_class_reference.symbol.latest.endswith('.WI')

    # Equities without LP in their name, .matches does a match using a regular
    # expression
    not_lp_name = ~morningstar.company_reference.standard_name.latest.matches('.* L[. ]?P.?$')

    # Equities with a null value in the limited_partnership Morningstar
    # fundamental field.
    not_lp_balance_sheet = morningstar.balance_sheet.limited_partnership.latest.isnull()

    # Equities whose most recent Morningstar market cap is not null have
    # fundamental data and therefore are not ETFs.
    have_market_cap = morningstar.valuation.market_cap.latest.notnull()

    # At least a certain price
    price = USEquityPricing.close.latest
    AtLeastPrice   = (price >= context.MyLeastPrice)
    AtMostPrice    = (price <= context.MyMostPrice)

    # Filter for stocks that pass all of our previous filters.
    tradeable_stocks = (
        primary_share
        & common_stock
        & not_depositary
        & not_otc
        & not_wi
        & not_lp_name
        & not_lp_balance_sheet
        & have_market_cap
        & AtLeastPrice
        & AtMostPrice
    )

    BottomVar=10
    LowVar=6
    HighVar=40

    log.info('\nAlgorithm initialized variables:\n BottomVar %s \n LowVar %s \n HighVar %s'
        % (BottomVar, LowVar, HighVar)
    )

    # High dollar volume filter.
    base_universe = AverageDollarVolume(
        window_length=20,
        mask=tradeable_stocks
    ).percentile_between(LowVar, HighVar)

    # Short close price average.
    ShortAvg = SimpleMovingAverage(
        inputs=[USEquityPricing.close],
        window_length=3,
        mask=base_universe
    )

    # Long close price average.
    LongAvg = SimpleMovingAverage(
        inputs=[USEquityPricing.close],
        window_length=45,
        mask=base_universe
    )

    percent_difference = (ShortAvg - LongAvg) / LongAvg

    # Filter to select securities to long.
    stocks_worst = percent_difference.bottom(BottomVar)
    securities_to_trade = (stocks_worst)

    return Pipeline(
        columns={
            'stocks_worst': stocks_worst
        },
        screen=(securities_to_trade),
    )

def my_compute_weights(context):
    """
    Compute ordering weights.
    """
    # Compute even target weights for our long positions and short positions.
    stocks_worst_weight = 1.00/len(context.stocks_worst)

    return stocks_worst_weight

def before_trading_start(context, data):
    # Gets our pipeline output every day.
    context.output = pipeline_output('my_pipeline')

    context.stocks_worst = context.output[context.output['stocks_worst']].index.tolist()

    context.stocks_worst_weight = my_compute_weights(context)
    pass

def my_rebalance(context, data):
    TakeProfitFactor=1.10
    GetOutFactor=.95
    GetInFactor=.97

    cash=context.portfolio.cash
    MaxPositionValue=context.portfolio.portfolio_value*context.MaxPositionFactor

    # Maybe Take Profit or Get Out because no longer in pipeline
    for stock in context.portfolio.positions:
        if data.can_trade(stock):
            Curr_P = float(data.current([stock], 'price'))
            if (
                Curr_P>context.portfolio.positions[stock].cost_basis*TakeProfitFactor
                or
                stock not in context.stocks_worst
            ):
                if get_open_orders(stock):
                    cancel_open_order(stock)
                StockShares = context.portfolio.positions[stock].amount
                StockSharesValue = StockShares * Curr_P
                order(stock, -StockShares,
                    style=LimitOrder(Curr_P*GetOutFactor)
                )
                cash += StockSharesValue

    if cash >= 10:
        for stock in context.stocks_worst:
            if data.can_trade(stock):
                Curr_P = float(data.current([stock], 'price'))
                if Curr_P>=context.MyLeastPrice+0.10:
                    StockShares = context.stocks_worst_weight*cash/Curr_P/76
                    if StockShares<1:
                        StockShares=1
                    if MaxPositionValue>StockShares*Curr_P:
                        order(stock, StockShares,
                            style=LimitOrder(Curr_P*GetInFactor)
                        )

def my_record_vars(context, data):
    """
    Record variables at the end of each day.
    """

    # Record our variables.
    record(leverage=context.account.leverage)
    longs = shorts = 0
    for position in context.portfolio.positions.itervalues():
        if position.amount > 0:
            longs += 1
        if position.amount < 0:
            shorts += 1
    record(long_count=longs, short_count=shorts)


def log_open_order(StockToLog):
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        if stock == StockToLog:
            for order in orders:
                message = 'Found open order for {amount} shares in {stock}'
                log.info(message.format(amount=order.amount, stock=stock))

def log_open_orders():
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        for order in orders:
            message = 'Found open order for {amount} shares in {stock}'
            log.info(message.format(amount=order.amount, stock=stock))

def cancel_open_order(StockToCancel):
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        if stock == StockToCancel:
            for order in orders:
                #message = 'Canceling order of {amount} shares in {stock}'
                #log.info(message.format(amount=order.amount, stock=stock))
                cancel_order(order)
def cancel_open_orders(context, data):
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        for order in orders:
            #message = 'Canceling order of {amount} shares in {stock}'
            #log.info(message.format(amount=order.amount, stock=stock))
            cancel_order(order)

# This is the every minute stuff
def handle_data(context, data):
    pass
There was a runtime error.

Hi Charles. Thanks for sharing your work. It quite interesting how the small stock could deliver a huge potential benefit. Im looking through your code and see this line and saw the constant number 76, what is purpose of this.
StockShares = context.stocks_worst_weight*cash/Curr_P/76
i'm trying to incorporate your strategy in a portfolio of strategies.
Thanks for your time and your work.
Wish you all the best and make a decent return.

[email protected]:~$ python
Python 2.7.12 (default, Jul 1 2016, 15:12:24)
[GCC 5.4.0 20160609] on linux2 Type "help", "copyright", "credits" or "license" for more information.

6.5*60
390.0
380/5
76

8) That is the actual text in the python interactive session where I calculated that number.
6.5 trading hours * 60 minutes = 390 minutes in a normal trading day
390 minus 5 minutes at beginning and end of trading day = 380
380 total trading minutes per normal trading day / 5 minute rebalancing = 76

It is not perfect. Feel free to modify

Thanks. I really appreciated your work. It changed my perspective about penny stocks.

Seems like lots were changed in your latest version from the last version such as securities_to_trade = (stocks_worst), my_rebalnce function, handle data function removed, robinhood gold removed, etc. Why such a drastic change ?

I actually went through some angst deciding whether or not to start a new thread called Robin Hood Plays Twister. That is because I like both versions nearly the same And also the new version is enough different that perhaps that would have been good way to go.

In the end, I decided that this new version is largely a cleaned up version, with some ideas that I was meaning to implement anyways. The RobinhoodGold code can be added back in easy enough. I didn't like having so many orders rejected. Robinhood is barely letting me use any of the "gold" anyways because low volume stocks have high volatility. They are however letting me use $2,000 of deposits immediately and proceeds of stock sells immediately, which is cool.

Since this morning, I am running the latest version in my IB paper account. But i noticed that all orders have been rejected with the reason "Your account has a minimum of 15 orders working on either buy or sell side". Not sure seeing similar rejection errors before. Any thoughts why all orders get rejected?

Hey Charles, this looks great, regarding the Robinhood Gold context property (UseRobinhoodGold), how come I can't find it in your latest code? Is that a special Quantopian context property that will modify the way trading works under the hood? I am a beginner in Quantopian and trading in general.

That's because every 5 mins passed if stock still in pipeline then we limit order 1 share of that stock which previously we ordered 1 shares at different price level ( sometime 2 orders is at the same price).
Example:
if your Bottom Var = 15
every 5 mins we have another 15 orders (price could be the same or different)
=> This is like accumulating shares for that particular stock through out the day. (Could be benefit because every time we buy it getting cheaper) This version could be a day trader because if stock at 9:30 is in pipeline but later during the day, if it is not anymore then it will sell that stock.

Due to previous conversations on The Gold King And His Knights, I believe that the pipeline is only calculated once per day before algo starts trading. On that other algorithm, there was a time that I was trying to make the factors that define the pipeline change every day. While trying to figure that out, I believe I learned that the pipeline is calculated only once per day. So, as far as I know, if it is in the pipeline early in the day, it will also be in the pipeline later in the day.

Having said that, this version of the algo is more likely to attempt day trades. If the 10% profit is reached in the same day that the shares were bought, then it will attempt to sell to take profit.

I'm a novice in this so forgive me is this question is off:

Is it possible for this backtest to be inaccurate due to it assuming that every order will be filled? This algo appears to work on low-val, low-vol stocks, so in the wild it will only get a fraction of any order filled, whereas the backtest will assume that every order is executed perfectly.

It may be too good to be true. Low volume stocks are tricky to backtest because your orders can have a huge impact on price movement besides liquidity problems. The only way to find out is to go live and become a millionaire!

Any success with live trading of this strategy? I've been running it in my IB paper account but only very few orders get filled and overall return yet negative. I guess no other way to figure out if it can be profitable but trade it with real money:(

@Charles

Hello Charles, hope all is going well with your algo. I have a quick question about Robinhood Gold since I saw you mentioned it. Would you be able to help?
Question

I've been live trading this slightly modified "pre-Twister" version of the algo since Monday. It does seem to have a hard time getting orders filled. To date, it is down 3.3%.

Clone Algorithm
8
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.pipeline import Pipeline
from quantopian.algorithm import attach_pipeline, pipeline_output
from quantopian.pipeline.data.builtin import USEquityPricing
from quantopian.pipeline.data import morningstar
from quantopian.pipeline.factors import SimpleMovingAverage, AverageDollarVolume
from quantopian.pipeline.filters.morningstar import IsPrimaryShare

def initialize(context):
    #set_commission(commission.PerShare(cost=0.01, min_trade_cost=1.50))
    set_slippage(slippage.VolumeShareSlippage(volume_limit=.20, price_impact=0.0))
    #set_slippage(slippage.FixedSlippage(spread=0.00))
    set_commission(commission.PerTrade(cost=0.00))
    #set_slippage(slippage.FixedSlippage(spread=0.00))
    set_long_only()
    
    context.UseRobinhoodGold=False #Set this to False if you do not have Robinhood Gold
    context.RobinhoodGold=2000

    context.PV=context.portfolio.portfolio_value
    context.NextDay=True
    context.Wait=False
    context.StartingWaitMin=10 # was 50
    context.WaitMin=context.StartingWaitMin
    #context.GIWeight=.66
    context.GIWeight=1.00
    #context.SSWeight=.34
    context.SSWeight=0

    schedule_function(StopWait, date_rules.month_start(days_offset=10), time_rules.market_open(hours=0, minutes=7))

    # Prevent excessive logging of canceled orders at market close.
    schedule_function(cancel_open_orders, date_rules.every_day(), time_rules.market_close(hours=0, minutes=7))

    # Record variables at the end of each day.
    schedule_function(my_record_vars, date_rules.every_day(), time_rules.market_close())

    # Create our pipeline and attach it to our algorithm.
    my_pipe = make_pipeline(context)
    attach_pipeline(my_pipe, 'my_pipeline')

def make_pipeline(context):
    """
    Create our pipeline.
    """

    # Filter for primary share equities. IsPrimaryShare is a built-in filter.
    primary_share = IsPrimaryShare()

    # Equities listed as common stock (as opposed to, say, preferred stock).
    # 'ST00000001' indicates common stock.
    common_stock = morningstar.share_class_reference.security_type.latest.eq('ST00000001')

    # Non-depositary receipts. Recall that the ~ operator inverts filters,
    # turning Trues into Falses and vice versa
    not_depositary = ~morningstar.share_class_reference.is_depositary_receipt.latest

    # Equities not trading over-the-counter.
    not_otc = ~morningstar.share_class_reference.exchange_id.latest.startswith('OTC')

    # Not when-issued equities.
    not_wi = ~morningstar.share_class_reference.symbol.latest.endswith('.WI')

    # Equities without LP in their name, .matches does a match using a regular
    # expression
    not_lp_name = ~morningstar.company_reference.standard_name.latest.matches('.* L[. ]?P.?$')

    # Equities with a null value in the limited_partnership Morningstar
    # fundamental field.
    not_lp_balance_sheet = morningstar.balance_sheet.limited_partnership.latest.isnull()

    # Equities whose most recent Morningstar market cap is not null have
    # fundamental data and therefore are not ETFs.
    have_market_cap = morningstar.valuation.market_cap.latest.notnull()

    # At least a certain price
    price = USEquityPricing.close.latest
    AtLeastPrice   = (price >= .80)
    AtMostPrice    = (price <= 3.00)

    # Filter for stocks that pass all of our previous filters.
    tradeable_stocks = (
        primary_share
        & common_stock
        & not_depositary
        & not_otc
        & not_wi
        & not_lp_name
        & not_lp_balance_sheet
        & have_market_cap
        & AtLeastPrice
        & AtMostPrice
    )

    BottomVar=10
    TopVar=10

    LowVar=6
    HighVar=40

    log.info('\nAlgorithm initialized variables:\n BottomVar %s \n TopVar %s \n LowVar %s \n HighVar %s'
        % (BottomVar, TopVar, LowVar, HighVar)
    )
    #record(BottomVar=BottomVar, TopVar=TopVar, LowVar=LowVar, HighVar=HighVar)

    # High dollar volume filter.
    base_universe = AverageDollarVolume(
        window_length=20,
        mask=tradeable_stocks
    ).percentile_between(LowVar, HighVar)

    # Short close price average.
    ShortAvg = SimpleMovingAverage(
        inputs=[USEquityPricing.close],
        window_length=3,
        mask=base_universe
    )

    # Long close price average.
    LongAvg = SimpleMovingAverage(
        inputs=[USEquityPricing.close],
        window_length=45,
        mask=base_universe
    )

    percent_difference = (ShortAvg - LongAvg) / LongAvg

    # Filter to select securities to long.
    stocks_worst = percent_difference.bottom(BottomVar)
    stocks_best = percent_difference.top(TopVar)
    securities_to_trade = (stocks_worst | stocks_best)

    return Pipeline(
        columns={
            'stocks_worst': stocks_worst,
            'stocks_best': stocks_best
        },
        screen=(securities_to_trade),
    )

def my_compute_weights(context):
    """
    Compute ordering weights.
    """
    # Compute even target weights for our long positions and short positions.
    stocks_worst_weight = context.GIWeight / len(context.stocks_worst)
    stocks_best_weight = context.SSWeight / len(context.stocks_best)

    return stocks_worst_weight, stocks_best_weight

def before_trading_start(context, data):
    context.NextDay=True

    # Gets our pipeline output every day.
    context.output = pipeline_output('my_pipeline')

    context.stocks_worst = context.output[context.output['stocks_worst']].index.tolist()
    context.stocks_best = context.output[context.output['stocks_best']].index.tolist()

    context.stocks_worst_weight, context.stocks_best_weight = my_compute_weights(context)
    pass

def my_rebalance(context, data):
    GetInFactor=.99 # was .94
    if context.NextDay:
        cancel_open_orders(context, data)

        cash=context.portfolio.cash / 2.0
        if context.UseRobinhoodGold:
            if cash >= context.RobinhoodGold:
                cash += context.RobinhoodGold
            else:
                cash *= 2

        for stock in context.portfolio.positions:
            if stock not in context.stocks_worst and stock not in context.stocks_best and data.can_trade(stock):
                StockShares = context.portfolio.positions[stock].amount
                Curr_P = float(data.current([stock], 'price'))
                StockSharesValue = StockShares * Curr_P
                order(stock, -StockShares,
                    style=LimitOrder(Curr_P)
                )
                #log.info('\nSELLING   %s   shares of   %s' % (StockSharesToSellNow, stock))
                cash += StockSharesValue

        log.info('\n%s   Probable cash balance AFTER rebalancing sells' % (cash))

        while cash >= 10:
            for stock in context.stocks_worst:
                if data.can_trade(stock):
                    Curr_P = float(data.current([stock], 'price'))
                    order_value(stock, context.stocks_worst_weight*cash,
                        style=LimitOrder(Curr_P*GetInFactor)
                    )
                    cash = cash - (context.stocks_worst_weight*cash)

        log.info('\n%s   Probable cash balance AFTER rebalancing buys' % (cash))

        context.NextDay=False

def my_record_vars(context, data):
    """
    Record variables at the end of each day.
    """

    # Record our variables.
    record(MaxPV=context.PV/context.portfolio.starting_cash, leverage=context.account.leverage)
    longs = shorts = 0
    for position in context.portfolio.positions.itervalues():
        if position.amount > 0:
            longs += 1
        if position.amount < 0:
            shorts += 1
    record(long_count=longs, short_count=shorts)


def log_open_order(StockToLog):
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        if stock == StockToLog:
            for order in orders:
                message = 'Found open order for {amount} shares in {stock}'
                log.info(message.format(amount=order.amount, stock=stock))

def log_open_orders():
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        for order in orders:
            message = 'Found open order for {amount} shares in {stock}'
            log.info(message.format(amount=order.amount, stock=stock))

def cancel_open_order(StockToCancel):
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        if stock == StockToCancel:
            for order in orders:
                #message = 'Canceling order of {amount} shares in {stock}'
                #log.info(message.format(amount=order.amount, stock=stock))
                cancel_order(order)
def cancel_open_orders(context, data):
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        for order in orders:
            #message = 'Canceling order of {amount} shares in {stock}'
            #log.info(message.format(amount=order.amount, stock=stock))
            cancel_order(order)

#Stop waiting
def StopWait(context, data):
    #The idea is to start fresh
    portfolio_value=context.portfolio.portfolio_value
    context.PV=portfolio_value
    context.Wait=False

# This is the every minute stuff
def handle_data(context, data):
    # Maybe Take Profit
    if context.NextDay:
        for stock in context.portfolio.positions:
            if data.can_trade(stock):
                Curr_P = float(data.current([stock], 'price'))
                if context.portfolio.positions[stock].cost_basis*1.25<Curr_P:
                    if data.can_trade(stock):
                        if get_open_orders(stock):
                            cancel_open_order(stock)
                        order_target_percent(stock, 0, style=LimitOrder(Curr_P*.95))

    if context.WaitMin==0:
        if context.NextDay:
            my_rebalance(context, data)

        context.WaitMin=context.StartingWaitMin

        GetOutFactor=1.25
        portfolio_value=context.portfolio.portfolio_value
        if portfolio_value < context.PV*.985 and context.account.leverage>=.33:
            context.Wait=True
            for stock in context.portfolio.positions:
                if data.can_trade(stock):
                    Curr_P = float(data.current([stock], 'price'))
                    if get_open_orders(stock):
                        continue #do NOT do anything new with this stock until the orders are filled or cancelled at end of day
                    if context.NextDay:
                        order_target_percent(stock, 0, style=LimitOrder(Curr_P*GetOutFactor))
            #context.GIWeight=.40
            context.GIWeight=1.00
        else:
            if portfolio_value > context.PV:
                context.PV=portfolio_value
            context.Wait=False
            #context.GIWeight+=.0006
            context.GIWeight=1.00

    if context.GIWeight < .40:
        context.GIWeight=.40
    if context.GIWeight > .66:
        context.GIWeight=.66
    context.GIWeight=1.00
    context.SSWeight=1-context.GIWeight

    context.WaitMin-=1
    if context.WaitMin<=0:
        context.WaitMin=0
There was a runtime error.

ok, sorry again
I found a glaring bug. My code that tries to limit any one position from getting too large, will not ever limit anything.

I fixed it.

I also made some adjustments to do all rebalancing in approximate the first two hours with larger individual orders.

Clone Algorithm
173
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.pipeline import Pipeline
from quantopian.algorithm import attach_pipeline, pipeline_output
from quantopian.pipeline.data.builtin import USEquityPricing
from quantopian.pipeline.data import morningstar
from quantopian.pipeline.factors import SimpleMovingAverage, AverageDollarVolume
from quantopian.pipeline.filters.morningstar import IsPrimaryShare

def initialize(context):
    #set_commission(commission.PerShare(cost=0.01, min_trade_cost=1.50))
    set_slippage(slippage.VolumeShareSlippage(volume_limit=.20, price_impact=0.0))
    #set_slippage(slippage.FixedSlippage(spread=0.00))
    set_commission(commission.PerTrade(cost=0.00))
    #set_slippage(slippage.FixedSlippage(spread=0.00))
    set_long_only()

    context.MyLeastPrice=0.80
    context.MyMostPrice=3.00
    context.MaxPositionFactor=0.10

    # Rebalance
    EveryThisManyMinutes=5
    for minutez in xrange(5, 125, EveryThisManyMinutes):
        schedule_function(my_rebalance, date_rules.every_day(), time_rules.market_open(minutes=minutez))

    # Prevent excessive logging of canceled orders at market close.
    schedule_function(cancel_open_orders, date_rules.every_day(), time_rules.market_close(hours=0, minutes=1))

    # Record variables at the end of each day.
    schedule_function(my_record_vars, date_rules.every_day(), time_rules.market_close())

    # Create our pipeline and attach it to our algorithm.
    my_pipe = make_pipeline(context)
    attach_pipeline(my_pipe, 'my_pipeline')

def make_pipeline(context):
    """
    Create our pipeline.
    """

    # Filter for primary share equities. IsPrimaryShare is a built-in filter.
    primary_share = IsPrimaryShare()

    # Equities listed as common stock (as opposed to, say, preferred stock).
    # 'ST00000001' indicates common stock.
    common_stock = morningstar.share_class_reference.security_type.latest.eq('ST00000001')

    # Non-depositary receipts. Recall that the ~ operator inverts filters,
    # turning Trues into Falses and vice versa
    not_depositary = ~morningstar.share_class_reference.is_depositary_receipt.latest

    # Equities not trading over-the-counter.
    not_otc = ~morningstar.share_class_reference.exchange_id.latest.startswith('OTC')

    # Not when-issued equities.
    not_wi = ~morningstar.share_class_reference.symbol.latest.endswith('.WI')

    # Equities without LP in their name, .matches does a match using a regular
    # expression
    not_lp_name = ~morningstar.company_reference.standard_name.latest.matches('.* L[. ]?P.?$')

    # Equities with a null value in the limited_partnership Morningstar
    # fundamental field.
    not_lp_balance_sheet = morningstar.balance_sheet.limited_partnership.latest.isnull()

    # Equities whose most recent Morningstar market cap is not null have
    # fundamental data and therefore are not ETFs.
    have_market_cap = morningstar.valuation.market_cap.latest.notnull()

    # At least a certain price
    price = USEquityPricing.close.latest
    AtLeastPrice   = (price >= context.MyLeastPrice)
    AtMostPrice    = (price <= context.MyMostPrice)

    # Filter for stocks that pass all of our previous filters.
    tradeable_stocks = (
        primary_share
        & common_stock
        & not_depositary
        & not_otc
        & not_wi
        & not_lp_name
        & not_lp_balance_sheet
        & have_market_cap
        & AtLeastPrice
        & AtMostPrice
    )

    BottomVar=10
    LowVar=6
    HighVar=40

    log.info('\nAlgorithm initialized variables:\n BottomVar %s \n LowVar %s \n HighVar %s'
        % (BottomVar, LowVar, HighVar)
    )

    # High dollar volume filter.
    base_universe = AverageDollarVolume(
        window_length=20,
        mask=tradeable_stocks
    ).percentile_between(LowVar, HighVar)

    # Short close price average.
    ShortAvg = SimpleMovingAverage(
        inputs=[USEquityPricing.close],
        window_length=3,
        mask=base_universe
    )

    # Long close price average.
    LongAvg = SimpleMovingAverage(
        inputs=[USEquityPricing.close],
        window_length=45,
        mask=base_universe
    )

    percent_difference = (ShortAvg - LongAvg) / LongAvg

    # Filter to select securities to long.
    stocks_worst = percent_difference.bottom(BottomVar)
    securities_to_trade = (stocks_worst)

    return Pipeline(
        columns={
            'stocks_worst': stocks_worst
        },
        screen=(securities_to_trade),
    )

def my_compute_weights(context):
    """
    Compute ordering weights.
    """
    # Compute even target weights for our long positions and short positions.
    stocks_worst_weight = 1.00/len(context.stocks_worst)

    return stocks_worst_weight

def before_trading_start(context, data):
    # Gets our pipeline output every day.
    context.output = pipeline_output('my_pipeline')

    context.stocks_worst = context.output[context.output['stocks_worst']].index.tolist()

    context.stocks_worst_weight = my_compute_weights(context)
    pass

def my_rebalance(context, data):
    TakeProfitFactor=1.10
    GetOutFactor=.95
    GetInFactor=.97

    cash=context.portfolio.cash
    MaxPositionValue=context.portfolio.portfolio_value*context.MaxPositionFactor

    # Maybe Take Profit or Get Out because no longer in pipeline
    for stock in context.portfolio.positions:
        if data.can_trade(stock):
            Curr_P = float(data.current([stock], 'price'))
            if (
                Curr_P>context.portfolio.positions[stock].cost_basis*TakeProfitFactor
                or
                stock not in context.stocks_worst
            ):
                if get_open_orders(stock):
                    cancel_open_order(stock)
                StockShares = context.portfolio.positions[stock].amount
                StockSharesValue = StockShares * Curr_P
                order(stock, -StockShares,
                    style=LimitOrder(Curr_P*GetOutFactor)
                )
                cash += StockSharesValue

    if cash >= 100:
        for stock in context.stocks_worst:
            if data.can_trade(stock):
                Curr_P = float(data.current([stock], 'price'))
                if Curr_P>=context.MyLeastPrice+0.10:
                    StockShares = context.stocks_worst_weight*cash/Curr_P/24
                    if StockShares<1:
                        StockShares=1
                    if (
                        MaxPositionValue>context.portfolio.positions[stock].amount*context.portfolio.positions[stock].cost_basis
                        and
                        cash>StockShares*Curr_P*GetInFactor
                    ):
                        order(stock, StockShares,
                            style=LimitOrder(Curr_P*GetInFactor)
                        )
                        cash -= StockShares*Curr_P*GetInFactor

def my_record_vars(context, data):
    """
    Record variables at the end of each day.
    """

    # Record our variables.
    record(leverage=context.account.leverage)
    longs = shorts = 0
    for position in context.portfolio.positions.itervalues():
        if position.amount > 0:
            longs += 1
        if position.amount < 0:
            shorts += 1
    record(long_count=longs, short_count=shorts)


def log_open_order(StockToLog):
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        if stock == StockToLog:
            for order in orders:
                message = 'Found open order for {amount} shares in {stock}'
                log.info(message.format(amount=order.amount, stock=stock))

def log_open_orders():
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        for order in orders:
            message = 'Found open order for {amount} shares in {stock}'
            log.info(message.format(amount=order.amount, stock=stock))

def cancel_open_order(StockToCancel):
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        if stock == StockToCancel:
            for order in orders:
                #message = 'Canceling order of {amount} shares in {stock}'
                #log.info(message.format(amount=order.amount, stock=stock))
                cancel_order(order)
def cancel_open_orders(context, data):
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        for order in orders:
            #message = 'Canceling order of {amount} shares in {stock}'
            #log.info(message.format(amount=order.amount, stock=stock))
            cancel_order(order)

# This is the every minute stuff
def handle_data(context, data):
    pass
There was a runtime error.

Do I need to enable or change any daytrade settings in Robinhood in order to make this algo work properly?

Sorry for the newb question, but I am new to all of this.

Vince.
If you are new to all this, then paper trader until you understand how everything put together (trading + investing + this alto). During that time, pick a safe strategy and invest safely. I know you may tell me to "%%% off", but if you got burn enough you will realize this too.
Hence, paper trade this algo until you understand then go live. Market and money are still there to trade and to get.

I've been trying to paper trade this strategy for last few days, but unfortunately almost all orders were rejected and only 2 orders were filled out of thousands. It looks like the strategy is trying to place too many orders and they all get rejected by IB. I dont wanna test it in the real money account if i cant figure out why it doesnt work in the paper account.

What is the go-to platform for paper trading? Robinhood doesn't seem to have paper trading capabilities.

i paper trade it in Interactive Brokers paper account.

What is the reason for setting the slippage's price_impact to 0 as opposed to the default 0.1?

All sells/buys are done with limit orders (known price) thus 0 slippage

Does this algorithm need to take into account the T+3 unsettled cash for cash accounts? I noticed I don't see any of the safeguards in this algorithm.

@ Richard, as far as I am aware, Charles is using either Robinhood Instant or Robinhold Gold and does not need to take into account the T+3 rule because unsettled cash is essentially loaned until it settles, and is therefore technically available for use immediately. If you aren't using an Instant or Gold account, I'm sure this algorithm could be modified to trade less frequently in order to allow cash to settle, although I'm not sure how that impact its various metrics.

Hey guys, wanted to point out an observation that might explain why live trading is performing worse than the Quantopian back test over the same period.

Quantopian incorrectly handles limit orders on the back test which results in overly optimistic results. Once the limit price is crossed, Q fills at the current market price and NOT the limit price. This is incorrect because brokers will always fill at your limit price in that scenario. Small cap stocks amplify this effect since their prices tend to move rapidly and with low volume. So you may be filling over multiple minutes as price continues to get better where as in reality you would just fill everything at the limit price.

The fact that this algo is using limit orders, which in theory should improve accuracy, and is instead ~2X off on returns just shows the magnitude of this effect.

Please be aware of this if you are going live!

Robert, I have been observing the fill orders between IB and RB. This I what I saw so far, In live trading, orders are either filled at the limit price or limit + few cents different. IB filled orders less slippage than RB. Will observe more.

@Robert if that's how Q behaves, then isn't that a bug? Have you reported it?

Yep it is a bug. Quantopian is aware and is tracking it in the link below. However, despite having a community sourced fix it appears to be stagnant for over a month. As a result, I wanted to make sure everyone was aware and didn't get burned since this bug has a large impact on the OP's algo in particular.

[Limit Order Bug Tracking][1] https://github.com/quantopian/zipline/pull/1376

Last activity on that PR was 17 days ago and they are discussing it internally. Also, it looks like they don't want to accept that PR and are proposing an alternative one.

It would be nice to have notification customization options for Robinhood. For example, an option to receive one spreadsheet (csv is preferable to excel) per day with all transactions, instead of individual emails. Even better would be to have the option to simply download upon request by date range and transaction type(s).

The reason I cancel all orders in the last minute before market close is to prevent all that noise in the logs. I am not currently using the logs for debugging. But it is easier now without all that noise.

My algo tends to execute small percentage of placed orders. And I am ok with that. That works to my advantage. However, the notifications can be overwhelming. I recommend that you automatically sort your Robinhood emails to folders for Placed, Canceled, and Executed (or filled if you prefer that).

Charles,

Thank you for being so transparent in your development process. Have you been able to nail down the source of the discrepancy between live trading vs. back test trading? My fear is that the discrepancy is due to the limit order bug mentioned above although I hope that is not the case. However, if it is, you will observe that your winning days aren't always as good as the equivalent time period in your back test while losing days are sometimes worse. The only way to know for sure is to check your fills line by line with the back test.

I only ask because I personally went through this experience and just want to pass on my lessons learned.

Robin Hood Plays Twister version Started Trading: 10/7/2016, 1:14:11 PM Capital base: $3,608.07
3.49% Returns $126.04 Dollar P/L 13.15 Sharpe $2,100.50 Long Exposure $1,633.61 Available Cash
-0.90% Benchmark

Robert, it is difficult to do that. I have some delisted stocks that I am holding on to, that have some effect on cash available. And I already own positions in most of these. And I stopped / started the algo multiple times this time around. The biggest effects seem to come from Robinhood not trading in certain stocks and partial fills and fills that are spread throughout the trading day. Not sure how to get the backtesting to more accurately reflect all of that. That is the purpose of slippage I suppose, but I haven't settled on accurate settings for that yet.

I can say, that I like the way this version is limiting buys to a max percentage of portfolio for each stock. The positions seem to be trending to be more evenly weighted now. Also, it does seem much less likely now to hold on to stocks that might get delisted.

Which version are you using? For some reason, the recent versions are showing weird behavior in real life.
Limit orders are getting put in throughout the day, but all the orders are of 1 share, and consists of many duplicate orders. (Rather than putting a larger limit order once).
Also the algo has been buying the same stocks ; notably it has been buying LTBR, ABAC, RXII, ATOS, etc. The pool of stocks in the pipeline does not seem to be varied.

Is this the same for you Charles?

Current positions in:
LTBR LBIX ABAC ATOS MSDI RXII BASI

orders are placed for 2 hours every 5 minutes ending at 10:30 Central
These are the 10:30 orders:
2016-10-11 10:30:00
BASI
Limit
7
$0.93 2016-10-11 10:30:00
LBIX
Limit
4
$1.58 2016-10-11 10:30:00
ABAC
Limit
3
$1.95 2016-10-11 10:30:00
RXII
Limit
4
$1.59 2016-10-11 10:30:00
ATOS
Limit
3
$1.89 2016-10-11 10:30:00
MIRN
Limit
4
$1.77 2016-10-11 10:30:00
MSDI
Limit
5
$1.39

The minimum order is 1 share. The current price has to be from $0.90 to $3.00.

The pipeline tends to change slightly every 2 or 3 days (maybe 4).

i am trading the latest version of the aglo in the IB paper account, and it keeps sending orders all day until the market close @ 4PM. Most of the orders are duplicate orders and they get rejected by the brokerage. Is it a normal behavior?

Rebalance

EveryThisManyMinutes=5  
for minutez in xrange(5, 125, EveryThisManyMinutes):  
    schedule_function(my_rebalance, date_rules.every_day(), time_rules.market_open(minutes=minutez))

Does that schedule for my_rebalance match yours? If it does, it should stop placing orders after 2 hours.
If it does not match, you are probably using a slightly older version of the algo which would place orders all trading day.

Thanks Charles, it was exactly the problem. It looks like i was trading not the most recent algo.

I am currently paper trading this algo using Q's paper trading platform and it has been trading more or less similar securities like you. Is it normal to be seeing a lot of canceled orders?

The current algo is using a 3% discount entry. So, yes there will be a lot of canceled orders. But you should end up with larger more balanced positions for close to 10 positions. Each position is limited to 10% of portfolio. It probably will average 6 to 8 positions all the time.

If you can have your email automatically send filled orders to a separate folder, it is easier to see the progress for each position.

I guess this algo will perform awful with IB (min $1 commission) and only can be traded profitably with $0 commissions?

Maxim,
Please try Robin Hood Forgot His Shorts. That is set up to hopefully be profitable with IB.
Naor Porat told me it is not working for him with IB.
Let us know if that works for you.
I don't have IB, so I cannot live trade it for testing.
If that seems to work for you, then I can possibly make additional tweaks to improve it.

Charles, can you re-post the latest algo you're using along with how it is performing - especially after the sell off yesterday?

As of 10:08AM Central,
-0.70% Returns -0.70% Benchmark ($26.57) Dollar P/L -0.95 Sharpe $1,686.52 Long Exposure $1,894.98 Available Cash

Clone Algorithm
173
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.pipeline import Pipeline
from quantopian.algorithm import attach_pipeline, pipeline_output
from quantopian.pipeline.data.builtin import USEquityPricing
from quantopian.pipeline.data import morningstar
from quantopian.pipeline.factors import SimpleMovingAverage, AverageDollarVolume
from quantopian.pipeline.filters.morningstar import IsPrimaryShare

def initialize(context):
    #set_commission(commission.PerShare(cost=0.01, min_trade_cost=1.50))
    set_slippage(slippage.VolumeShareSlippage(volume_limit=.20, price_impact=0.0))
    #set_slippage(slippage.FixedSlippage(spread=0.00))
    set_commission(commission.PerTrade(cost=0.00))
    #set_slippage(slippage.FixedSlippage(spread=0.00))
    set_long_only()

    context.MyLeastPrice=0.80
    context.MyMostPrice=3.00
    context.MaxPositionFactor=0.10

    # Rebalance
    EveryThisManyMinutes=5
    for minutez in xrange(5, 125, EveryThisManyMinutes):
        schedule_function(my_rebalance, date_rules.every_day(), time_rules.market_open(minutes=minutez))

    # Prevent excessive logging of canceled orders at market close.
    schedule_function(cancel_open_orders, date_rules.every_day(), time_rules.market_close(hours=0, minutes=1))

    # Record variables at the end of each day.
    schedule_function(my_record_vars, date_rules.every_day(), time_rules.market_close())

    # Create our pipeline and attach it to our algorithm.
    my_pipe = make_pipeline(context)
    attach_pipeline(my_pipe, 'my_pipeline')

def make_pipeline(context):
    """
    Create our pipeline.
    """

    # Filter for primary share equities. IsPrimaryShare is a built-in filter.
    primary_share = IsPrimaryShare()

    # Equities listed as common stock (as opposed to, say, preferred stock).
    # 'ST00000001' indicates common stock.
    common_stock = morningstar.share_class_reference.security_type.latest.eq('ST00000001')

    # Non-depositary receipts. Recall that the ~ operator inverts filters,
    # turning Trues into Falses and vice versa
    not_depositary = ~morningstar.share_class_reference.is_depositary_receipt.latest

    # Equities not trading over-the-counter.
    not_otc = ~morningstar.share_class_reference.exchange_id.latest.startswith('OTC')

    # Not when-issued equities.
    not_wi = ~morningstar.share_class_reference.symbol.latest.endswith('.WI')

    # Equities without LP in their name, .matches does a match using a regular
    # expression
    not_lp_name = ~morningstar.company_reference.standard_name.latest.matches('.* L[. ]?P.?$')

    # Equities with a null value in the limited_partnership Morningstar
    # fundamental field.
    not_lp_balance_sheet = morningstar.balance_sheet.limited_partnership.latest.isnull()

    # Equities whose most recent Morningstar market cap is not null have
    # fundamental data and therefore are not ETFs.
    have_market_cap = morningstar.valuation.market_cap.latest.notnull()

    # At least a certain price
    price = USEquityPricing.close.latest
    AtLeastPrice   = (price >= context.MyLeastPrice)
    AtMostPrice    = (price <= context.MyMostPrice)

    # Filter for stocks that pass all of our previous filters.
    tradeable_stocks = (
        primary_share
        & common_stock
        & not_depositary
        & not_otc
        & not_wi
        & not_lp_name
        & not_lp_balance_sheet
        & have_market_cap
        & AtLeastPrice
        & AtMostPrice
    )

    BottomVar=10
    LowVar=6
    HighVar=40

    log.info('\nAlgorithm initialized variables:\n BottomVar %s \n LowVar %s \n HighVar %s'
        % (BottomVar, LowVar, HighVar)
    )

    # High dollar volume filter.
    base_universe = AverageDollarVolume(
        window_length=20,
        mask=tradeable_stocks
    ).percentile_between(LowVar, HighVar)

    # Short close price average.
    ShortAvg = SimpleMovingAverage(
        inputs=[USEquityPricing.close],
        window_length=3,
        mask=base_universe
    )

    # Long close price average.
    LongAvg = SimpleMovingAverage(
        inputs=[USEquityPricing.close],
        window_length=45,
        mask=base_universe
    )

    percent_difference = (ShortAvg - LongAvg) / LongAvg

    # Filter to select securities to long.
    stocks_worst = percent_difference.bottom(BottomVar)
    securities_to_trade = (stocks_worst)

    return Pipeline(
        columns={
            'stocks_worst': stocks_worst
        },
        screen=(securities_to_trade),
    )

def my_compute_weights(context):
    """
    Compute ordering weights.
    """
    # Compute even target weights for our long positions and short positions.
    stocks_worst_weight = 1.00/len(context.stocks_worst)

    return stocks_worst_weight

def before_trading_start(context, data):
    # Gets our pipeline output every day.
    context.output = pipeline_output('my_pipeline')

    context.stocks_worst = context.output[context.output['stocks_worst']].index.tolist()

    context.stocks_worst_weight = my_compute_weights(context)
    pass

def my_rebalance(context, data):
    TakeProfitFactor=1.10
    GetOutFactor=.95
    GetInFactor=.97

    cash=context.portfolio.cash
    MaxPositionValue=context.portfolio.portfolio_value*context.MaxPositionFactor

    # Maybe Take Profit or Get Out because no longer in pipeline
    for stock in context.portfolio.positions:
        if data.can_trade(stock):
            Curr_P = float(data.current([stock], 'price'))
            if (
                Curr_P>context.portfolio.positions[stock].cost_basis*TakeProfitFactor
                or
                stock not in context.stocks_worst
            ):
                if get_open_orders(stock):
                    cancel_open_order(stock)
                StockShares = context.portfolio.positions[stock].amount
                StockSharesValue = StockShares * Curr_P
                order(stock, -StockShares,
                    style=LimitOrder(Curr_P*GetOutFactor)
                )
                cash += StockSharesValue

    if cash >= 100:
        for stock in context.stocks_worst:
            if data.can_trade(stock):
                Curr_P = float(data.current([stock], 'price'))
                if Curr_P>=context.MyLeastPrice+0.10:
                    StockShares = context.stocks_worst_weight*cash/Curr_P/24
                    if StockShares<1:
                        StockShares=1
                    if (
                        MaxPositionValue>context.portfolio.positions[stock].amount*context.portfolio.positions[stock].cost_basis
                        and
                        cash>StockShares*Curr_P*GetInFactor
                    ):
                        order(stock, StockShares,
                            style=LimitOrder(Curr_P*GetInFactor)
                        )
                        cash -= StockShares*Curr_P*GetInFactor

def my_record_vars(context, data):
    """
    Record variables at the end of each day.
    """

    # Record our variables.
    record(leverage=context.account.leverage)
    longs = shorts = 0
    for position in context.portfolio.positions.itervalues():
        if position.amount > 0:
            longs += 1
        if position.amount < 0:
            shorts += 1
    record(long_count=longs, short_count=shorts)


def log_open_order(StockToLog):
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        if stock == StockToLog:
            for order in orders:
                message = 'Found open order for {amount} shares in {stock}'
                log.info(message.format(amount=order.amount, stock=stock))

def log_open_orders():
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        for order in orders:
            message = 'Found open order for {amount} shares in {stock}'
            log.info(message.format(amount=order.amount, stock=stock))

def cancel_open_order(StockToCancel):
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        if stock == StockToCancel:
            for order in orders:
                #message = 'Canceling order of {amount} shares in {stock}'
                #log.info(message.format(amount=order.amount, stock=stock))
                cancel_order(order)
def cancel_open_orders(context, data):
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        for order in orders:
            #message = 'Canceling order of {amount} shares in {stock}'
            #log.info(message.format(amount=order.amount, stock=stock))
            cancel_order(order)

# This is the every minute stuff
def handle_data(context, data):
    pass
There was a runtime error.

How is is comparing to the backtest? I've noticed that previous algos do not match their backtest due to limit orders.

@Charles

For Robinhood Gold, I am curious to know whether the API provides Margin Maintenance and other metrics the app gives you to manage your portfolio? In general, do you get any additional info regarding RH Gold here on Q or does the margin act like extra cash in your account?

Thanks Charles for pointing me to the Robin Hood Forgot His Shorts thread. What are the main differences between Robin Hood Throws A Party and Robin Hood Forgot His Shorts?

I'll be trading Robin Hood Forgot His Shorts thread in my paper account for a few days and if everything goes well, i'll try it in my IB live account.

So what is the best fitted version for IB live trading by now?
The last backtest posted?

Does this algo, or any for that matter, play nice with manual orders on Robin Hood? As in, if I'm still holding a previously purchased stock when the algo goes live, will it consider that stock when buying/selling or will it ignore it? Especially if it is over the dollar limits imposed by the script.

It will try to sell it unless you put the protection in

Hey, Charles , i saw many rejected order due to this 5 cents increment only in some stocks

I tried running this and the high number of pending orders quickly tied-up my available cash. Even if a later order would fill, the previous pending orders are preventing it. Charles mentions that all pending orders are cancelled at the end of day. Might it be useful to have orders not filled within X hours be cancelled? Otherwise, absent a lot of selling, pending orders will prevent buying beyond the first hour or two after open.

Robin Hood Plays Twister BETA
Stopped on 10/18/2016, 3:00:05 PM
-3.32% Returns ($119.92) Dollar P/L -3.96 Sharpe $2,018.17 Long Exposure $1,469.98 Available Cash

Hopefully, this new version completely avoids the 5 cent increment. https://www.sec.gov/news/pressrelease/2015-82.html
"and a volume weighted average price of at least $2.00 for every trading day".

Clone Algorithm
173
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.pipeline import Pipeline
from quantopian.algorithm import attach_pipeline, pipeline_output
from quantopian.pipeline.data.builtin import USEquityPricing
from quantopian.pipeline.data import morningstar
from quantopian.pipeline.factors import SimpleMovingAverage, AverageDollarVolume
from quantopian.pipeline.filters.morningstar import IsPrimaryShare

def initialize(context):
    #set_commission(commission.PerShare(cost=0.01, min_trade_cost=1.50))
    set_slippage(slippage.VolumeShareSlippage(volume_limit=.20, price_impact=0.0))
    #set_slippage(slippage.FixedSlippage(spread=0.00))
    set_commission(commission.PerTrade(cost=0.00))
    #set_slippage(slippage.FixedSlippage(spread=0.00))
    set_long_only()

    context.MyNumberOfPositions=7
    context.MyLeastPrice=1.25
    context.MyMostPrice=1.50
    context.MaxPositionFactor=1.00/context.MyNumberOfPositions

    # Rebalance
    context.RepeatThisManyTimes=5
    context.EveryThisManyMinutes=43
    for minutez in xrange(
        7, 
        context.EveryThisManyMinutes*context.RepeatThisManyTimes, 
        context.EveryThisManyMinutes
    ):
        schedule_function(my_rebalance, date_rules.every_day(), time_rules.market_open(minutes=minutez))

    # Prevent excessive logging of canceled orders at market close.
    schedule_function(cancel_open_orders, date_rules.every_day(), time_rules.market_close(hours=0, minutes=1))

    # Record variables at the end of each day.
    schedule_function(my_record_vars, date_rules.every_day(), time_rules.market_close())

    # Create our pipeline and attach it to our algorithm.
    my_pipe = make_pipeline(context)
    attach_pipeline(my_pipe, 'my_pipeline')

def make_pipeline(context):
    """
    Create our pipeline.
    """

    # Filter for primary share equities. IsPrimaryShare is a built-in filter.
    primary_share = IsPrimaryShare()

    # Equities listed as common stock (as opposed to, say, preferred stock).
    # 'ST00000001' indicates common stock.
    common_stock = morningstar.share_class_reference.security_type.latest.eq('ST00000001')

    # Non-depositary receipts. Recall that the ~ operator inverts filters,
    # turning Trues into Falses and vice versa
    not_depositary = ~morningstar.share_class_reference.is_depositary_receipt.latest

    # Equities not trading over-the-counter.
    not_otc = ~morningstar.share_class_reference.exchange_id.latest.startswith('OTC')

    # Not when-issued equities.
    not_wi = ~morningstar.share_class_reference.symbol.latest.endswith('.WI')

    # Equities without LP in their name, .matches does a match using a regular
    # expression
    not_lp_name = ~morningstar.company_reference.standard_name.latest.matches('.* L[. ]?P.?$')

    # Equities with a null value in the limited_partnership Morningstar
    # fundamental field.
    not_lp_balance_sheet = morningstar.balance_sheet.limited_partnership.latest.isnull()

    # Equities whose most recent Morningstar market cap is not null have
    # fundamental data and therefore are not ETFs.
    have_market_cap = morningstar.valuation.market_cap.latest.notnull()

    # At least a certain price
    price = USEquityPricing.close.latest
    AtLeastPrice   = (price >= context.MyLeastPrice)
    AtMostPrice    = (price <= context.MyMostPrice)

    # Filter for stocks that pass all of our previous filters.
    tradeable_stocks = (
        primary_share
        & common_stock
        & not_depositary
        & not_otc
        & not_wi
        & not_lp_name
        & not_lp_balance_sheet
        & have_market_cap
        & AtLeastPrice
        & AtMostPrice
    )

    LowVar=6
    HighVar=40

    log.info('\nAlgorithm initialized variables:\n context.MyNumberOfPositions %s \n LowVar %s \n HighVar %s'
        % (context.MyNumberOfPositions, LowVar, HighVar)
    )

    # High dollar volume filter.
    base_universe = AverageDollarVolume(
        window_length=20,
        mask=tradeable_stocks
    ).percentile_between(LowVar, HighVar)

    # Short close price average.
    ShortAvg = SimpleMovingAverage(
        inputs=[USEquityPricing.close],
        window_length=3,
        mask=base_universe
    )

    # Long close price average.
    LongAvg = SimpleMovingAverage(
        inputs=[USEquityPricing.close],
        window_length=45,
        mask=base_universe
    )

    percent_difference = (ShortAvg - LongAvg) / LongAvg

    # Filter to select securities to long.
    stocks_worst = percent_difference.bottom(context.MyNumberOfPositions)
    securities_to_trade = (stocks_worst)

    return Pipeline(
        columns={
            'stocks_worst': stocks_worst
        },
        screen=(securities_to_trade),
    )

def my_compute_weights(context):
    """
    Compute ordering weights.
    """
    # Compute even target weights for our long positions and short positions.
    stocks_worst_weight = 1.00/len(context.stocks_worst)

    return stocks_worst_weight

def before_trading_start(context, data):
    # Gets our pipeline output every day.
    context.output = pipeline_output('my_pipeline')

    context.stocks_worst = context.output[context.output['stocks_worst']].index.tolist()

    context.stocks_worst_weight = my_compute_weights(context)
    pass

def my_rebalance(context, data):
    TakeProfitFactor=1.10
    GetOutFactor=.95
    GetInFactor=.97

    cash=context.portfolio.cash
    MaxPositionValue=context.portfolio.portfolio_value*context.MaxPositionFactor

    # Maybe Take Profit or Get Out because no longer in pipeline
    for stock in context.portfolio.positions:
        if data.can_trade(stock):
            Curr_P = float(data.current([stock], 'price'))
            if (
                Curr_P>context.portfolio.positions[stock].cost_basis*TakeProfitFactor
                or
                stock not in context.stocks_worst
            ):
                if get_open_orders(stock):
                    cancel_open_order(stock)
                StockShares = context.portfolio.positions[stock].amount
                StockSharesValue = StockShares * Curr_P
                order(stock, -StockShares,
                    style=LimitOrder(Curr_P*GetOutFactor)
                )
                cash += StockSharesValue

    if cash >= 100:
        for stock in context.stocks_worst:
            if data.can_trade(stock):
                Curr_P = float(data.current([stock], 'price'))
                if Curr_P>=context.MyLeastPrice:
                    StockShares = context.stocks_worst_weight*cash/Curr_P/context.RepeatThisManyTimes
                    if StockShares<1:
                        StockShares=1
                    if (
                        MaxPositionValue>context.portfolio.positions[stock].amount*context.portfolio.positions[stock].cost_basis
                        and
                        cash>StockShares*Curr_P*GetInFactor
                    ):
                        order(stock, StockShares,
                            style=LimitOrder(Curr_P*GetInFactor)
                        )
                        cash -= StockShares*Curr_P*GetInFactor

def my_record_vars(context, data):
    """
    Record variables at the end of each day.
    """

    # Record our variables.
    record(leverage=context.account.leverage)
    longs = shorts = 0
    for position in context.portfolio.positions.itervalues():
        if position.amount > 0:
            longs += 1
        if position.amount < 0:
            shorts += 1
    record(long_count=longs, short_count=shorts)


def log_open_order(StockToLog):
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        if stock == StockToLog:
            for order in orders:
                message = 'Found open order for {amount} shares in {stock}'
                log.info(message.format(amount=order.amount, stock=stock))

def log_open_orders():
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        for order in orders:
            message = 'Found open order for {amount} shares in {stock}'
            log.info(message.format(amount=order.amount, stock=stock))

def cancel_open_order(StockToCancel):
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        if stock == StockToCancel:
            for order in orders:
                #message = 'Canceling order of {amount} shares in {stock}'
                #log.info(message.format(amount=order.amount, stock=stock))
                cancel_order(order)
def cancel_open_orders(context, data):
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        for order in orders:
            #message = 'Canceling order of {amount} shares in {stock}'
            #log.info(message.format(amount=order.amount, stock=stock))
            cancel_order(order)

# This is the every minute stuff
def handle_data(context, data):
    pass
There was a runtime error.

Right

Anyone live trading this? Results in last week have been sideways to dismal. Hard to keep invested, but a lot of backtests dip for a couple of days before turning up.

@Charles any thought of adding a filter to ignore specific stocks? I've had DELT orders attempted the last two days, but are rejected by Robinhood. That eliminates a position for the day.

Agreed. Market conditions at this time may be the "perfect storm" that we have to wait out. Or it is still possible that most of the nice returns in the back tests are not even close to reality, which at this time looks grim.

I have swung at least temporarily to this much more conservative version. More changes to come in the future. I am hoping this version at least proves to be consistently profitable, at least beating the benchmark and most mutual funds / index funds.

Clone Algorithm
173
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.pipeline import Pipeline
from quantopian.algorithm import attach_pipeline, pipeline_output
from quantopian.pipeline.data.builtin import USEquityPricing
from quantopian.pipeline.data import morningstar
from quantopian.pipeline.factors import SimpleMovingAverage, AverageDollarVolume
from quantopian.pipeline.filters.morningstar import IsPrimaryShare

def initialize(context):
    #set_commission(commission.PerShare(cost=0.01, min_trade_cost=1.50))
    set_slippage(slippage.VolumeShareSlippage(volume_limit=.20, price_impact=0.0))
    #set_slippage(slippage.FixedSlippage(spread=0.00))
    set_commission(commission.PerTrade(cost=0.00))
    #set_slippage(slippage.FixedSlippage(spread=0.00))
    set_long_only()

    context.MyNumberOfPositions=7
    context.MyLeastPrice=1.25
    context.MyMostPrice=1.50
    context.MaxPositionFactor=1.00/context.MyNumberOfPositions

    # Rebalance
    context.RepeatThisManyTimes=5
    context.EveryThisManyMinutes=43
    for minutez in xrange(
        7, 
        context.EveryThisManyMinutes*context.RepeatThisManyTimes, 
        context.EveryThisManyMinutes
    ):
        schedule_function(my_rebalance, date_rules.every_day(), time_rules.market_open(minutes=minutez))

    # Prevent excessive logging of canceled orders at market close.
    schedule_function(cancel_open_orders, date_rules.every_day(), time_rules.market_close(hours=0, minutes=1))

    # Record variables at the end of each day.
    schedule_function(my_record_vars, date_rules.every_day(), time_rules.market_close())

    # Create our pipeline and attach it to our algorithm.
    my_pipe = make_pipeline(context)
    attach_pipeline(my_pipe, 'my_pipeline')

def make_pipeline(context):
    """
    Create our pipeline.
    """

    # Filter for primary share equities. IsPrimaryShare is a built-in filter.
    primary_share = IsPrimaryShare()

    # Equities listed as common stock (as opposed to, say, preferred stock).
    # 'ST00000001' indicates common stock.
    common_stock = morningstar.share_class_reference.security_type.latest.eq('ST00000001')

    # Non-depositary receipts. Recall that the ~ operator inverts filters,
    # turning Trues into Falses and vice versa
    not_depositary = ~morningstar.share_class_reference.is_depositary_receipt.latest

    # Equities not trading over-the-counter.
    not_otc = ~morningstar.share_class_reference.exchange_id.latest.startswith('OTC')

    # Not when-issued equities.
    not_wi = ~morningstar.share_class_reference.symbol.latest.endswith('.WI')

    # Equities without LP in their name, .matches does a match using a regular
    # expression
    not_lp_name = ~morningstar.company_reference.standard_name.latest.matches('.* L[. ]?P.?$')

    # Equities with a null value in the limited_partnership Morningstar
    # fundamental field.
    not_lp_balance_sheet = morningstar.balance_sheet.limited_partnership.latest.isnull()

    # Equities whose most recent Morningstar market cap is not null have
    # fundamental data and therefore are not ETFs.
    have_market_cap = morningstar.valuation.market_cap.latest.notnull()

    # At least a certain price
    price = USEquityPricing.close.latest
    AtLeastPrice   = (price >= context.MyLeastPrice)
    AtMostPrice    = (price <= context.MyMostPrice)

    # Filter for stocks that pass all of our previous filters.
    tradeable_stocks = (
        primary_share
        & common_stock
        & not_depositary
        & not_otc
        & not_wi
        & not_lp_name
        & not_lp_balance_sheet
        & have_market_cap
        & AtLeastPrice
        & AtMostPrice
    )

    LowVar=6
    HighVar=40

    log.info('\nAlgorithm initialized variables:\n context.MyNumberOfPositions %s \n LowVar %s \n HighVar %s'
        % (context.MyNumberOfPositions, LowVar, HighVar)
    )

    # High dollar volume filter.
    base_universe = AverageDollarVolume(
        window_length=20,
        mask=tradeable_stocks
    ).percentile_between(LowVar, HighVar)

    # Short close price average.
    ShortAvg = SimpleMovingAverage(
        inputs=[USEquityPricing.close],
        window_length=3,
        mask=base_universe
    )

    # Long close price average.
    LongAvg = SimpleMovingAverage(
        inputs=[USEquityPricing.close],
        window_length=45,
        mask=base_universe
    )

    percent_difference = (ShortAvg - LongAvg) / LongAvg

    # Filter to select securities to long.
    stocks_worst = percent_difference.bottom(context.MyNumberOfPositions)
    securities_to_trade = (stocks_worst)

    return Pipeline(
        columns={
            'stocks_worst': stocks_worst
        },
        screen=(securities_to_trade),
    )

def my_compute_weights(context):
    """
    Compute ordering weights.
    """
    # Compute even target weights for our long positions and short positions.
    stocks_worst_weight = 1.00/len(context.stocks_worst)

    return stocks_worst_weight

def before_trading_start(context, data):
    # Gets our pipeline output every day.
    context.output = pipeline_output('my_pipeline')

    context.stocks_worst = context.output[context.output['stocks_worst']].index.tolist()

    context.stocks_worst_weight = my_compute_weights(context)
    pass

def my_rebalance(context, data):
    TakeProfitFactor=1.06
    GetOutFactor=.99
    GetInFactor=.92
    BuyMoreMinPrice=float((context.MyLeastPrice+context.MyMostPrice)/2)
    cash=context.portfolio.cash
    MaxPositionValue=context.portfolio.portfolio_value*context.MaxPositionFactor

    # Maybe Take Profit or Get Out because no longer in pipeline
    for stock in context.portfolio.positions:
        if data.can_trade(stock):
            CurrPrice = float(data.current([stock], 'price'))
            CostBasis = float(context.portfolio.positions[stock].cost_basis)
            if (
                CurrPrice>CostBasis*TakeProfitFactor
                or
                stock not in context.stocks_worst
            ):
                if get_open_orders(stock):
                    cancel_open_order(stock)
                StockShares = context.portfolio.positions[stock].amount
                StockSharesValue = StockShares * CurrPrice
                GetOutPrice = float(CurrPrice*GetOutFactor)
                if CostBasis>GetOutPrice:
                    GetOutPrice=float((GetOutPrice+CostBasis)/2)
                order(stock, -StockShares,
                    style=LimitOrder(GetOutPrice)
                )
                cash += StockSharesValue

    if cash >= 100:
        for stock in context.stocks_worst:
            if data.can_trade(stock):
                CurrPrice = float(data.current([stock], 'price'))
                if CurrPrice>=BuyMoreMinPrice:
                    StockShares = context.stocks_worst_weight*cash/CurrPrice/context.RepeatThisManyTimes
                    if StockShares<1:
                        StockShares=1
                    if (
                        MaxPositionValue>context.portfolio.positions[stock].amount*context.portfolio.positions[stock].cost_basis
                        and
                        cash>StockShares*CurrPrice*GetInFactor
                    ):
                        order(stock, StockShares,
                            style=LimitOrder(CurrPrice*GetInFactor)
                        )
                        cash -= StockShares*CurrPrice*GetInFactor

def my_record_vars(context, data):
    """
    Record variables at the end of each day.
    """

    # Record our variables.
    record(leverage=context.account.leverage)
    longs = shorts = 0
    for position in context.portfolio.positions.itervalues():
        if position.amount > 0:
            longs += 1
        if position.amount < 0:
            shorts += 1
    record(long_count=longs, short_count=shorts)


def log_open_order(StockToLog):
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        if stock == StockToLog:
            for order in orders:
                message = 'Found open order for {amount} shares in {stock}'
                log.info(message.format(amount=order.amount, stock=stock))

def log_open_orders():
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        for order in orders:
            message = 'Found open order for {amount} shares in {stock}'
            log.info(message.format(amount=order.amount, stock=stock))

def cancel_open_order(StockToCancel):
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        if stock == StockToCancel:
            for order in orders:
                #message = 'Canceling order of {amount} shares in {stock}'
                #log.info(message.format(amount=order.amount, stock=stock))
                cancel_order(order)
def cancel_open_orders(context, data):
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        for order in orders:
            #message = 'Canceling order of {amount} shares in {stock}'
            #log.info(message.format(amount=order.amount, stock=stock))
            cancel_order(order)

# This is the every minute stuff
def handle_data(context, data):
    pass
There was a runtime error.

Any changes other than the Profit/In/Out factors?

It won't buy more shares into a position, unless the current price is at least halfway into our min max range. I did that so that we don't immediately sell the next day a position that dropped below min price.

If cost basis is greater than get out price, then we go halfway to the cost basis to make that the new get out price.

I like the more conservative nature of it. I see that leverage is about half of the earlier versions. Likely because it often holds less than the max positioins allowed. Is there a simple way to increase the size of the orders to compensate?

As is, no.

However, I am brainstorming different possibilities of having half the portfolio controlled by the algorithm, leaving the other half manually managed by the user. Or having multiple algos in the same algo. With signals being sent to it to control the factors, etc by the user.

If the current version proves profitable, then I can focus on the other ideas. Right now, I'm just tired of losing money, which is the current reality.

I am not running this in robinhood, but running it on quantopian live mode. Over the last week it is up ~3% (the one from a backtest posted 3 weeks ago) but I have no way of knowing if this will hold true in live trading because to me this is your biggest risk point:

set_slippage(slippage.VolumeShareSlippage(volume_limit=.20, price_impact=0.0))  

How did you come to set your slippage to this and how did you determine if it accurately replicates live trading conditions for low volume stocks? It could be artificially inflating your backtests by allowing you to purchase stock at a limit price that would never be met in real life.

To your point about combining multiple strategies, I've found a way to do it and have sucessfully implemented it live, BUT it won't work with this strategy the way it's currently programmed. Although I think it would be a great candidate. Essentially you have to program a way to control your leverage on this strategy for it to work. For example: set leverage to .5 and it initiates buys/sells up to the limit. Currently you could do something like this:

    context.MyNumberOfPositions=7  
    context.maxleverage = 1.0  
    context.MaxPositionFactor=context.maxleverage/context.MyNumberOfPositions  

but the algo only gets to a maximum of ~.25 leverage. IF you could find a way to make it fully execute up to the maximum it would be possible to integrate it into a combined strategy. My ideal would be some sort of low volitility pipeline value/momentum strategy which would compliment this one nicely I think.

Ok, I think this is a step in the right direction. I think it stands a fighting chance of large returns and it also much more often reaches 1.0 leverage.
Caution though, manually sell any stocks that seem to be creeping toward delisting.

This one, with some tweaking of the code, seems like it would be easier to combine with other algos, if you wish.

Clone Algorithm
68
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.pipeline import Pipeline
from quantopian.algorithm import attach_pipeline, pipeline_output
from quantopian.pipeline.data.builtin import USEquityPricing
from quantopian.pipeline.data import morningstar
from quantopian.pipeline.factors import SimpleMovingAverage, AverageDollarVolume
from quantopian.pipeline.filters.morningstar import IsPrimaryShare

def initialize(context):
    #set_commission(commission.PerShare(cost=0.01, min_trade_cost=1.50))
    set_slippage(slippage.VolumeShareSlippage(volume_limit=.20, price_impact=0.0))
    #set_slippage(slippage.FixedSlippage(spread=0.00))
    set_commission(commission.PerTrade(cost=0.00))
    #set_slippage(slippage.FixedSlippage(spread=0.00))
    set_long_only()

    context.MyNumberOfCandidates=10
    context.MyLeastPrice=1.33
    context.MyMostPrice=1.88

    # Rebalance
    EveryThisManyMinutes=7
    TradingDayHours=6.5
    TradingDayMinutes=int((TradingDayHours*60)-(EveryThisManyMinutes*2))
    for minutez in xrange(
        EveryThisManyMinutes, 
        TradingDayMinutes, 
        EveryThisManyMinutes
    ):
        schedule_function(my_rebalance, date_rules.every_day(), time_rules.market_open(minutes=minutez))

    # Prevent excessive logging of canceled orders at market close.
    schedule_function(cancel_open_orders, date_rules.every_day(), time_rules.market_close(hours=0, minutes=1))

    # Record variables at the end of each day.
    schedule_function(my_record_vars, date_rules.every_day(), time_rules.market_close())

    # Create our pipeline and attach it to our algorithm.
    my_pipe = make_pipeline(context)
    attach_pipeline(my_pipe, 'my_pipeline')

def make_pipeline(context):
    """
    Create our pipeline.
    """

    # Filter for primary share equities. IsPrimaryShare is a built-in filter.
    primary_share = IsPrimaryShare()

    # Equities listed as common stock (as opposed to, say, preferred stock).
    # 'ST00000001' indicates common stock.
    common_stock = morningstar.share_class_reference.security_type.latest.eq('ST00000001')

    # Non-depositary receipts. Recall that the ~ operator inverts filters,
    # turning Trues into Falses and vice versa
    not_depositary = ~morningstar.share_class_reference.is_depositary_receipt.latest

    # Equities not trading over-the-counter.
    not_otc = ~morningstar.share_class_reference.exchange_id.latest.startswith('OTC')

    # Not when-issued equities.
    not_wi = ~morningstar.share_class_reference.symbol.latest.endswith('.WI')

    # Equities without LP in their name, .matches does a match using a regular
    # expression
    not_lp_name = ~morningstar.company_reference.standard_name.latest.matches('.* L[. ]?P.?$')

    # Equities with a null value in the limited_partnership Morningstar
    # fundamental field.
    not_lp_balance_sheet = morningstar.balance_sheet.limited_partnership.latest.isnull()

    # Equities whose most recent Morningstar market cap is not null have
    # fundamental data and therefore are not ETFs.
    have_market_cap = morningstar.valuation.market_cap.latest.notnull()

    # At least a certain price
    price = USEquityPricing.close.latest
    AtLeastPrice   = (price >= context.MyLeastPrice)
    AtMostPrice    = (price <= context.MyMostPrice)

    # Filter for stocks that pass all of our previous filters.
    tradeable_stocks = (
        primary_share
        & common_stock
        & not_depositary
        & not_otc
        & not_wi
        & not_lp_name
        & not_lp_balance_sheet
        & have_market_cap
        & AtLeastPrice
        & AtMostPrice
    )

    LowVar=6
    HighVar=40

    log.info('\nAlgorithm initialized variables:\n context.MyNumberOfCandidates %s \n LowVar %s \n HighVar %s'
        % (context.MyNumberOfCandidates, LowVar, HighVar)
    )

    # High dollar volume filter.
    base_universe = AverageDollarVolume(
        window_length=20,
        mask=tradeable_stocks
    ).percentile_between(LowVar, HighVar)

    # Short close price average.
    ShortAvg = SimpleMovingAverage(
        inputs=[USEquityPricing.close],
        window_length=3,
        mask=base_universe
    )

    # Long close price average.
    LongAvg = SimpleMovingAverage(
        inputs=[USEquityPricing.close],
        window_length=45,
        mask=base_universe
    )

    percent_difference = (ShortAvg - LongAvg) / LongAvg

    # Filter to select securities to long.
    stocks_worst = percent_difference.bottom(context.MyNumberOfCandidates)
    securities_to_trade = (stocks_worst)

    return Pipeline(
        columns={
            'stocks_worst': stocks_worst
        },
        screen=(securities_to_trade),
    )

def my_compute_weights(context):
    """
    Compute ordering weights.
    """
    # Compute even target weights for our long positions and short positions.
    stocks_worst_weight = 1.00/len(context.stocks_worst)

    return stocks_worst_weight

def before_trading_start(context, data):
    # Gets our pipeline output every day.
    context.output = pipeline_output('my_pipeline')

    context.stocks_worst = context.output[context.output['stocks_worst']].index.tolist()

    context.stocks_worst_weight = my_compute_weights(context)

    from itertools import cycle
    context.MyCandidate = cycle(context.stocks_worst)

    pass

def my_rebalance(context, data):
    cancel_open_orders(context, data)
    
    BuyFactor=.965
    SellFactor=1.08
    cash=context.portfolio.cash

    # Order sell at profit target in case somebody actually buys it
    for stock in context.portfolio.positions:
        if data.can_trade(stock):
            CurrPrice = float(data.current([stock], 'price'))
            CostBasis = float(context.portfolio.positions[stock].cost_basis)
            StockShares = context.portfolio.positions[stock].amount
            SellPrice = float(CostBasis*SellFactor)
            order(stock, -StockShares,
                style=LimitOrder(SellPrice)
            )

    stock = context.MyCandidate.next()
    if data.can_trade(stock):
        CurrPrice = float(data.current([stock], 'price'))
        StockShares = int(cash/CurrPrice*BuyFactor)
        if cash>StockShares*CurrPrice*BuyFactor:
            order(stock, StockShares,
                style=LimitOrder(CurrPrice*BuyFactor)
            )

def my_record_vars(context, data):
    """
    Record variables at the end of each day.
    """

    # Record our variables.
    record(leverage=context.account.leverage)
    longs = shorts = 0
    for position in context.portfolio.positions.itervalues():
        if position.amount > 0:
            longs += 1
        if position.amount < 0:
            shorts += 1
    record(long_count=longs, short_count=shorts)


def log_open_order(StockToLog):
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        if stock == StockToLog:
            for order in orders:
                message = 'Found open order for {amount} shares in {stock}'
                log.info(message.format(amount=order.amount, stock=stock))

def log_open_orders():
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        for order in orders:
            message = 'Found open order for {amount} shares in {stock}'
            log.info(message.format(amount=order.amount, stock=stock))

def cancel_open_order(StockToCancel):
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        if stock == StockToCancel:
            for order in orders:
                #message = 'Canceling order of {amount} shares in {stock}'
                #log.info(message.format(amount=order.amount, stock=stock))
                cancel_order(order)
def cancel_open_orders(context, data):
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        for order in orders:
            #message = 'Canceling order of {amount} shares in {stock}'
            #log.info(message.format(amount=order.amount, stock=stock))
            cancel_order(order)

# Very easy cycle through a list
def cycle(my_list, start_at=None):
    start_at = 0 if start_at is None else my_list.index(start_at)
    while True:
        yield my_list[start_at]
        start_at = (start_at + 1) % len(my_list)

# This is the every minute stuff
def handle_data(context, data):
    pass
There was a runtime error.

Thanks for the regular updates. There are two things that I noticed with this version. It day trades on the backtests. So if RH's PDT protections are working, those trades will be rejected. Might be better or worse on the next day. Second, those trades sometimes use full or close to full leverage in a single stock. Luckily it is good at picking winners, but a bit nervous putting all the eggs in one penny stock.

All your points I agree with. So EYES WIDE OPEN foks! Buyer beware.
Also, still not clear what best slippage settings to use. And there is that apparent bug in backtesting where limit orders on low volume stocks get better prices than they would have live trading. Again, buyer beware.

This is more efficient. It only issues a sell order if no orders exist already. Not perfect, but closer to what I want.

Clone Algorithm
68
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.pipeline import Pipeline
from quantopian.algorithm import attach_pipeline, pipeline_output
from quantopian.pipeline.data.builtin import USEquityPricing
from quantopian.pipeline.data import morningstar
from quantopian.pipeline.factors import SimpleMovingAverage, AverageDollarVolume
from quantopian.pipeline.filters.morningstar import IsPrimaryShare

def initialize(context):
    #set_commission(commission.PerShare(cost=0.01, min_trade_cost=1.50))
    set_slippage(slippage.VolumeShareSlippage(volume_limit=.20, price_impact=0.0))
    #set_slippage(slippage.FixedSlippage(spread=0.00))
    set_commission(commission.PerTrade(cost=0.00))
    #set_slippage(slippage.FixedSlippage(spread=0.00))
    set_long_only()

    context.MyNumberOfCandidates=10
    context.MyLeastPrice=1.33
    context.MyMostPrice=1.88

    # Rebalance
    EveryThisManyMinutes=7
    TradingDayHours=6.5
    TradingDayMinutes=int((TradingDayHours*60)-(EveryThisManyMinutes*2))
    for minutez in xrange(
        EveryThisManyMinutes, 
        TradingDayMinutes, 
        EveryThisManyMinutes
    ):
        schedule_function(my_rebalance, date_rules.every_day(), time_rules.market_open(minutes=minutez))

    # Prevent excessive logging of canceled orders at market close.
    schedule_function(cancel_open_orders, date_rules.every_day(), time_rules.market_close(hours=0, minutes=1))

    # Record variables at the end of each day.
    schedule_function(my_record_vars, date_rules.every_day(), time_rules.market_close())

    # Create our pipeline and attach it to our algorithm.
    my_pipe = make_pipeline(context)
    attach_pipeline(my_pipe, 'my_pipeline')

def make_pipeline(context):
    """
    Create our pipeline.
    """

    # Filter for primary share equities. IsPrimaryShare is a built-in filter.
    primary_share = IsPrimaryShare()

    # Equities listed as common stock (as opposed to, say, preferred stock).
    # 'ST00000001' indicates common stock.
    common_stock = morningstar.share_class_reference.security_type.latest.eq('ST00000001')

    # Non-depositary receipts. Recall that the ~ operator inverts filters,
    # turning Trues into Falses and vice versa
    not_depositary = ~morningstar.share_class_reference.is_depositary_receipt.latest

    # Equities not trading over-the-counter.
    not_otc = ~morningstar.share_class_reference.exchange_id.latest.startswith('OTC')

    # Not when-issued equities.
    not_wi = ~morningstar.share_class_reference.symbol.latest.endswith('.WI')

    # Equities without LP in their name, .matches does a match using a regular
    # expression
    not_lp_name = ~morningstar.company_reference.standard_name.latest.matches('.* L[. ]?P.?$')

    # Equities with a null value in the limited_partnership Morningstar
    # fundamental field.
    not_lp_balance_sheet = morningstar.balance_sheet.limited_partnership.latest.isnull()

    # Equities whose most recent Morningstar market cap is not null have
    # fundamental data and therefore are not ETFs.
    have_market_cap = morningstar.valuation.market_cap.latest.notnull()

    # At least a certain price
    price = USEquityPricing.close.latest
    AtLeastPrice   = (price >= context.MyLeastPrice)
    AtMostPrice    = (price <= context.MyMostPrice)

    # Filter for stocks that pass all of our previous filters.
    tradeable_stocks = (
        primary_share
        & common_stock
        & not_depositary
        & not_otc
        & not_wi
        & not_lp_name
        & not_lp_balance_sheet
        & have_market_cap
        & AtLeastPrice
        & AtMostPrice
    )

    LowVar=6
    HighVar=40

    log.info('\nAlgorithm initialized variables:\n context.MyNumberOfCandidates %s \n LowVar %s \n HighVar %s'
        % (context.MyNumberOfCandidates, LowVar, HighVar)
    )

    # High dollar volume filter.
    base_universe = AverageDollarVolume(
        window_length=20,
        mask=tradeable_stocks
    ).percentile_between(LowVar, HighVar)

    # Short close price average.
    ShortAvg = SimpleMovingAverage(
        inputs=[USEquityPricing.close],
        window_length=3,
        mask=base_universe
    )

    # Long close price average.
    LongAvg = SimpleMovingAverage(
        inputs=[USEquityPricing.close],
        window_length=45,
        mask=base_universe
    )

    percent_difference = (ShortAvg - LongAvg) / LongAvg

    # Filter to select securities to long.
    stocks_worst = percent_difference.bottom(context.MyNumberOfCandidates)
    securities_to_trade = (stocks_worst)

    return Pipeline(
        columns={
            'stocks_worst': stocks_worst
        },
        screen=(securities_to_trade),
    )

def my_compute_weights(context):
    """
    Compute ordering weights.
    """
    # Compute even target weights for our long positions and short positions.
    stocks_worst_weight = 1.00/len(context.stocks_worst)

    return stocks_worst_weight

def before_trading_start(context, data):
    # Gets our pipeline output every day.
    context.output = pipeline_output('my_pipeline')

    context.stocks_worst = context.output[context.output['stocks_worst']].index.tolist()

    context.stocks_worst_weight = my_compute_weights(context)

    from itertools import cycle
    context.MyCandidate = cycle(context.stocks_worst)

    pass

def my_rebalance(context, data):
    BuyFactor=.965
    SellFactor=1.08
    cash=context.portfolio.cash

    cancel_open_buy_orders(context, data)

    # Order sell at profit target in hope that somebody actually buys it
    for stock in context.portfolio.positions:
        if not get_open_orders(stock):
            CurrPrice = float(data.current([stock], 'price'))
            CostBasis = float(context.portfolio.positions[stock].cost_basis)
            StockShares = context.portfolio.positions[stock].amount
            SellPrice = float(CostBasis*SellFactor)
            order(stock, -StockShares,
                style=LimitOrder(SellPrice)
            )

    StockToBuy = context.MyCandidate.next()
    CurrPrice = float(data.current([StockToBuy], 'price'))
    StockShares = int(cash/CurrPrice*BuyFactor)
    if cash>StockShares*CurrPrice*BuyFactor:
        order(StockToBuy, StockShares,
            style=LimitOrder(CurrPrice*BuyFactor)
        )

def my_record_vars(context, data):
    """
    Record variables at the end of each day.
    """

    # Record our variables.
    record(leverage=context.account.leverage)
    longs = shorts = 0
    for position in context.portfolio.positions.itervalues():
        if position.amount > 0:
            longs += 1
        if position.amount < 0:
            shorts += 1
    record(long_count=longs, short_count=shorts)


def log_open_order(StockToLog):
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        if stock == StockToLog:
            for order in orders:
                message = 'Found open order for {amount} shares in {stock}'
                log.info(message.format(amount=order.amount, stock=stock))

def log_open_orders():
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        for order in orders:
            message = 'Found open order for {amount} shares in {stock}'
            log.info(message.format(amount=order.amount, stock=stock))

def cancel_open_buy_orders(context, data):
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        for order in orders:
            #message = 'Canceling order of {amount} shares in {stock}'
            #log.info(message.format(amount=order.amount, stock=stock))
            if 0<order.amount: #it is a buy order
                cancel_order(order)

def cancel_open_orders(context, data):
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        for order in orders:
            #message = 'Canceling order of {amount} shares in {stock}'
            #log.info(message.format(amount=order.amount, stock=stock))
            cancel_order(order)

# This is the every minute stuff
def handle_data(context, data):
    pass
There was a runtime error.

I'd call this an inelegant way of preventing day trades in the backtest. I'm a novice at python, so comments or improvements are welcome. It does appear to keep buying or selling the same stock in a given day. This period's results aren't bad, but YTD has a drawdown of over 43% with a 27% return.

Clone Algorithm
11
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.pipeline import Pipeline
from quantopian.algorithm import attach_pipeline, pipeline_output
from quantopian.pipeline.data.builtin import USEquityPricing
from quantopian.pipeline.data import morningstar
from quantopian.pipeline.factors import SimpleMovingAverage, AverageDollarVolume
from quantopian.pipeline.filters.morningstar import IsPrimaryShare

def initialize(context):
    #set_commission(commission.PerShare(cost=0.01, min_trade_cost=1.50))
    set_slippage(slippage.VolumeShareSlippage(volume_limit=.20, price_impact=0.0))
    #set_slippage(slippage.FixedSlippage(spread=0.00))
    set_commission(commission.PerTrade(cost=0.00))
    #set_slippage(slippage.FixedSlippage(spread=0.00))
    set_long_only()

    context.MyNumberOfCandidates=10
    context.MyLeastPrice=1.33
    context.MyMostPrice=1.88

    # Rebalance
    EveryThisManyMinutes=7
    TradingDayHours=6.5
    TradingDayMinutes=int((TradingDayHours*60)-(EveryThisManyMinutes*2))
    for minutez in xrange(
        EveryThisManyMinutes, 
        TradingDayMinutes, 
        EveryThisManyMinutes
    ):
        schedule_function(my_rebalance, date_rules.every_day(), time_rules.market_open(minutes=minutez))

    # Prevent excessive logging of canceled orders at market close.
    schedule_function(cancel_open_orders, date_rules.every_day(), time_rules.market_close(hours=0, minutes=1))

    # Record variables at the end of each day.
    schedule_function(my_record_vars, date_rules.every_day(), time_rules.market_close())

    # Create our pipeline and attach it to our algorithm.
    my_pipe = make_pipeline(context)
    attach_pipeline(my_pipe, 'my_pipeline')

def make_pipeline(context):
    """
    Create our pipeline.
    """

    # Filter for primary share equities. IsPrimaryShare is a built-in filter.
    primary_share = IsPrimaryShare()

    # Equities listed as common stock (as opposed to, say, preferred stock).
    # 'ST00000001' indicates common stock.
    common_stock = morningstar.share_class_reference.security_type.latest.eq('ST00000001')

    # Non-depositary receipts. Recall that the ~ operator inverts filters,
    # turning Trues into Falses and vice versa
    not_depositary = ~morningstar.share_class_reference.is_depositary_receipt.latest

    # Equities not trading over-the-counter.
    not_otc = ~morningstar.share_class_reference.exchange_id.latest.startswith('OTC')

    # Not when-issued equities.
    not_wi = ~morningstar.share_class_reference.symbol.latest.endswith('.WI')

    # Equities without LP in their name, .matches does a match using a regular
    # expression
    not_lp_name = ~morningstar.company_reference.standard_name.latest.matches('.* L[. ]?P.?$')

    # Equities with a null value in the limited_partnership Morningstar
    # fundamental field.
    not_lp_balance_sheet = morningstar.balance_sheet.limited_partnership.latest.isnull()

    # Equities whose most recent Morningstar market cap is not null have
    # fundamental data and therefore are not ETFs.
    have_market_cap = morningstar.valuation.market_cap.latest.notnull()

    # At least a certain price
    price = USEquityPricing.close.latest
    AtLeastPrice   = (price >= context.MyLeastPrice)
    AtMostPrice    = (price <= context.MyMostPrice)

    # Filter for stocks that pass all of our previous filters.
    tradeable_stocks = (
        primary_share
        & common_stock
        & not_depositary
        & not_otc
        & not_wi
        & not_lp_name
        & not_lp_balance_sheet
        & have_market_cap
        & AtLeastPrice
        & AtMostPrice
    )

    LowVar=6
    HighVar=40

    log.info('\nAlgorithm initialized variables:\n context.MyNumberOfCandidates %s \n LowVar %s \n HighVar %s'
        % (context.MyNumberOfCandidates, LowVar, HighVar)
    )

    # High dollar volume filter.
    base_universe = AverageDollarVolume(
        window_length=20,
        mask=tradeable_stocks
    ).percentile_between(LowVar, HighVar)

    # Short close price average.
    ShortAvg = SimpleMovingAverage(
        inputs=[USEquityPricing.close],
        window_length=3,
        mask=base_universe
    )

    # Long close price average.
    LongAvg = SimpleMovingAverage(
        inputs=[USEquityPricing.close],
        window_length=45,
        mask=base_universe
    )

    percent_difference = (ShortAvg - LongAvg) / LongAvg

    # Filter to select securities to long.
    stocks_worst = percent_difference.bottom(context.MyNumberOfCandidates)
    securities_to_trade = (stocks_worst)

    return Pipeline(
        columns={
            'stocks_worst': stocks_worst
        },
        screen=(securities_to_trade),
    )

def my_compute_weights(context):
    """
    Compute ordering weights.
    """
    # Compute even target weights for our long positions and short positions.
    stocks_worst_weight = 1.00/len(context.stocks_worst)

    return stocks_worst_weight

def before_trading_start(context, data):
    # Gets our pipeline output every day.
    context.output = pipeline_output('my_pipeline')

    context.stocks_worst = context.output[context.output['stocks_worst']].index.tolist()

    context.stocks_worst_weight = my_compute_weights(context)

    from itertools import cycle
    context.MyCandidate = cycle(context.stocks_worst)

    context.bought = []
    context.sold = []
    pass

def my_rebalance(context, data):
    BuyFactor=.965
    SellFactor=1.08
    cash=context.portfolio.cash
    
    cancel_open_buy_orders(context, data)

    # Order sell at profit target in hope that somebody actually buys it
    for stock in context.portfolio.positions:
        if not get_open_orders(stock):
            CurrPrice = float(data.current([stock], 'price'))
            CostBasis = float(context.portfolio.positions[stock].cost_basis)
            StockShares = context.portfolio.positions[stock].amount
            SellPrice = float(CostBasis*SellFactor)
            if get_datetime().date() and stock in context.bought:
                return
            else:
                order(stock, -StockShares,
                    style=LimitOrder(SellPrice)
                )
                sell = data[stock].datetime.date()
                # buystock = StockToBuy
                context.sold.append(sell)
                context.sold.append(stock)

    StockToBuy = context.MyCandidate.next()
    CurrPrice = float(data.current([StockToBuy], 'price'))
    StockShares = int(cash/CurrPrice*BuyFactor)
    if StockToBuy in context.sold:
        return
    else:
        if cash>StockShares*CurrPrice*BuyFactor:
            order(StockToBuy, StockShares,
            style=LimitOrder(CurrPrice*BuyFactor)
        )
            buy = data[StockToBuy].datetime.date()
            # buystock = StockToBuy
            context.bought.append(buy)
            context.bought.append(StockToBuy)
        
        #log.info('\n context.bought %s' % (context.bought))
                 
def my_record_vars(context, data):
    """
    Record variables at the end of each day.
    """

    # Record our variables.
    record(leverage=context.account.leverage)
    longs = 0
    for position in context.portfolio.positions.itervalues():
        if position.amount > 0:
            longs += 1

    record(long_count=longs)


def log_open_order(StockToLog):
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        if stock == StockToLog:
            for order in orders:
                message = 'Found open order for {amount} shares in {stock}'
                log.info(message.format(amount=order.amount, stock=stock))

def log_open_orders():
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        for order in orders:
            message = 'Found open order for {amount} shares in {stock}'
            log.info(message.format(amount=order.amount, stock=stock))

def cancel_open_buy_orders(context, data):
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        for order in orders:
            #message = 'Canceling order of {amount} shares in {stock}'
            #log.info(message.format(amount=order.amount, stock=stock))
            if 0<order.amount: #it is a buy order
                cancel_order(order)

def cancel_open_orders(context, data):
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        for order in orders:
            #message = 'Canceling order of {amount} shares in {stock}'
            #log.info(message.format(amount=order.amount, stock=stock))
            cancel_order(order)
    context.bought = []
    context.sold = []
# This is the every minute stuff
def handle_data(context, data):
    pass
There was a runtime error.

That looks like it probably works. I specifically am not avoiding day trades, so I don't plan on using it. I just use Rh day trade protection, because I still want to day trade up to my limit.
But it looks like reasonable code for preventing day trades. I think it's good, if that is the behavior you want.

It is more for backtesting than live trading. I was curious to see how much the results changed without the day trades.

I've encountered backtests where it takes a large position of a bad stock. The stock only goes down after purchase and doesn't recover for months. I've had it tie up 30-40-50% of the portfolio for 6-months or more. That drags down the returns. Would it be difficult to code a stop loss or to liquidate after holding a stock for X number of days?

Charles, how is your latest iteration of the code doing?

This last couple of weeks have been brutal. I am working on a new version.
Andy, this algo does not need leverage. Depending on the version, it rarely reaches 1.0 leverage.

HI Charles, I live tested your latest iteration and the stop loss used all 3 day trades within 1 hour of the market opening.

This has a builtin "stop loss". I think it will do better in these perilous times. It is a work in progress.

To Andy: I added day trade protection. Shout out to Dave Andrews. I basically used his day trade protection code.

Clone Algorithm
68
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.pipeline import Pipeline
from quantopian.algorithm import attach_pipeline, pipeline_output
from quantopian.pipeline.data.builtin import USEquityPricing
from quantopian.pipeline.data import morningstar
from quantopian.pipeline.factors import SimpleMovingAverage, AverageDollarVolume
from quantopian.pipeline.filters.morningstar import IsPrimaryShare

import numpy as np #needed for NaN handling

def initialize(context):
    #set_commission(commission.PerShare(cost=0.01, min_trade_cost=1.50))
    set_slippage(slippage.VolumeShareSlippage(volume_limit=.20, price_impact=0.0))
    #set_slippage(slippage.FixedSlippage(spread=0.00))
    set_commission(commission.PerTrade(cost=0.00))
    #set_slippage(slippage.FixedSlippage(spread=0.00))
    set_long_only()

    context.MyNumberOfCandidates=100
    context.MyLeastPrice=1.05
    context.MyMostPrice=1.49

    # Rebalance
    EveryThisManyMinutes=3
    TradingDayHours=6.5
    TradingDayMinutes=int((TradingDayHours*60)-(EveryThisManyMinutes*2))
    for minutez in xrange(
        EveryThisManyMinutes, 
        TradingDayMinutes, 
        EveryThisManyMinutes
    ):
        schedule_function(my_rebalance, date_rules.every_day(), time_rules.market_open(minutes=minutez))

    # Prevent excessive logging of canceled orders at market close.
    schedule_function(cancel_open_orders, date_rules.every_day(), time_rules.market_close(hours=0, minutes=1))

    # Record variables at the end of each day.
    schedule_function(my_record_vars, date_rules.every_day(), time_rules.market_close())

    # Create our pipeline and attach it to our algorithm.
    my_pipe = make_pipeline(context)
    attach_pipeline(my_pipe, 'my_pipeline')

def make_pipeline(context):
    """
    Create our pipeline.
    """

    # Filter for primary share equities. IsPrimaryShare is a built-in filter.
    primary_share = IsPrimaryShare()

    # Equities listed as common stock (as opposed to, say, preferred stock).
    # 'ST00000001' indicates common stock.
    common_stock = morningstar.share_class_reference.security_type.latest.eq('ST00000001')

    # Non-depositary receipts. Recall that the ~ operator inverts filters,
    # turning Trues into Falses and vice versa
    not_depositary = ~morningstar.share_class_reference.is_depositary_receipt.latest

    # Equities not trading over-the-counter.
    not_otc = ~morningstar.share_class_reference.exchange_id.latest.startswith('OTC')

    # Not when-issued equities.
    not_wi = ~morningstar.share_class_reference.symbol.latest.endswith('.WI')

    # Equities without LP in their name, .matches does a match using a regular
    # expression
    not_lp_name = ~morningstar.company_reference.standard_name.latest.matches('.* L[. ]?P.?$')

    # Equities with a null value in the limited_partnership Morningstar
    # fundamental field.
    not_lp_balance_sheet = morningstar.balance_sheet.limited_partnership.latest.isnull()

    # Equities whose most recent Morningstar market cap is not null have
    # fundamental data and therefore are not ETFs.
    have_market_cap = morningstar.valuation.market_cap.latest.notnull()

    # At least a certain price
    price = USEquityPricing.close.latest
    AtLeastPrice   = (price >= context.MyLeastPrice)
    AtMostPrice    = (price <= context.MyMostPrice)

    # Filter for stocks that pass all of our previous filters.
    tradeable_stocks = (
        primary_share
        & common_stock
        & not_depositary
        & not_otc
        & not_wi
        & not_lp_name
        & not_lp_balance_sheet
        & have_market_cap
        & AtLeastPrice
        & AtMostPrice
    )

    LowVar=6
    HighVar=40

    log.info('\nAlgorithm initialized variables:\n context.MyNumberOfCandidates %s \n LowVar %s \n HighVar %s'
        % (context.MyNumberOfCandidates, LowVar, HighVar)
    )

    # High dollar volume filter.
    base_universe = AverageDollarVolume(
        window_length=20,
        mask=tradeable_stocks
    ).percentile_between(LowVar, HighVar)

    # Short close price average.
    ShortAvg = SimpleMovingAverage(
        inputs=[USEquityPricing.close],
        window_length=3,
        mask=base_universe
    )

    # Long close price average.
    LongAvg = SimpleMovingAverage(
        inputs=[USEquityPricing.close],
        window_length=45,
        mask=base_universe
    )

    percent_difference = (ShortAvg - LongAvg) / LongAvg

    # Filter to select securities to long.
    stocks_worst = percent_difference.bottom(context.MyNumberOfCandidates)
    securities_to_trade = (stocks_worst)

    return Pipeline(
        columns={
            'stocks_worst': stocks_worst
        },
        screen=(securities_to_trade),
    )

def my_compute_weights(context):
    """
    Compute ordering weights.
    """
    # Compute even target weights for our long positions and short positions.
    stocks_worst_weight = 1.00/len(context.stocks_worst)

    return stocks_worst_weight

def before_trading_start(context, data):
    # Gets our pipeline output every day.
    context.output = pipeline_output('my_pipeline')

    context.stocks_worst = context.output[context.output['stocks_worst']].index.tolist()

    context.stocks_worst_weight = my_compute_weights(context)

    from itertools import cycle
    context.MyCandidate = cycle(context.stocks_worst)
    
    context.bought = []
    context.sold = []

    pass

def my_rebalance(context, data):
    BuyFactor=.9950
    SellFactor=1.33 #no worries, this gets auto reduced
    cash=context.portfolio.cash
    PositionCount=len(context.portfolio.positions)
    if 1>PositionCount:
        PositionCount=1
    PositionFactor=float(PositionCount*.005)
    LeverageFactor=float(context.account.leverage/PositionCount*5)

    cancel_open_buy_orders(context, data)

    # Order sell at profit target in hope that somebody actually buys it
    for stock in context.portfolio.positions:
        if not get_open_orders(stock):
            StockShares = context.portfolio.positions[stock].amount
            CurrPrice = float(data.current([stock], 'price'))
            CostBasis = float(context.portfolio.positions[stock].cost_basis)
            ProfitLossFactor = float(CurrPrice/CostBasis)
            MySellFactor = float((SellFactor*ProfitLossFactor)-PositionFactor-LeverageFactor)
            SellPrice = float(CostBasis*MySellFactor)
            if .01>SellPrice:
                SellPrice = .01
            if np.isnan(SellPrice) or stock in context.bought: #avoid day trade
                pass # probably best to wait until nan goes away
            else:
                order(stock, -StockShares,
                    style=LimitOrder(SellPrice)
                )
                context.sold.append(stock)


    stock = context.MyCandidate.next()
    CurrPrice = float(data.current([stock], 'price'))
    if np.isnan(CurrPrice) or stock in context.sold: #avoid day trade
        pass # probably best to wait until nan goes away
    else:
        StockShares = int(cash/CurrPrice*BuyFactor)
        if cash>StockShares*CurrPrice*BuyFactor:
            order(stock, StockShares,
                style=LimitOrder(CurrPrice*BuyFactor)
            )

def my_record_vars(context, data):
    """
    Record variables at the end of each day.
    """

    # Record our variables.
    record(leverage=context.account.leverage)
    longs = shorts = 0
    for position in context.portfolio.positions.itervalues():
        if position.amount > 0:
            longs += 1
        if position.amount < 0:
            shorts += 1
    record(long_count=longs, short_count=shorts)


def log_open_order(StockToLog):
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        if stock == StockToLog:
            for order in orders:
                message = 'Found open order for {amount} shares in {stock}'
                log.info(message.format(amount=order.amount, stock=stock))

def log_open_orders():
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        for order in orders:
            message = 'Found open order for {amount} shares in {stock}'
            log.info(message.format(amount=order.amount, stock=stock))

def cancel_open_buy_orders(context, data):
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        for order in orders:
            #message = 'Canceling order of {amount} shares in {stock}'
            #log.info(message.format(amount=order.amount, stock=stock))
            if 0<order.amount: #it is a buy order
                cancel_order(order)

def cancel_open_orders(context, data):
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        for order in orders:
            #message = 'Canceling order of {amount} shares in {stock}'
            #log.info(message.format(amount=order.amount, stock=stock))
            cancel_order(order)

# This is the every minute stuff
def handle_data(context, data):
    pass
There was a runtime error.

Thanks Charles. Is it also supposed to go over 50% into one stock? I thought with the previous iterations you wanted it to buy a couple here and there.

I think it is missing "context.sold.append(stock)" at the end of the buy section. It will buy and then sell in the same day, but won't sell and then buy more. Adding that around line 204 fixes it.

Big drawdowns in the little testing I've been able to do so far. Hope to have time later this afternoon to poke around more.

I tried the recent algo and it bought one stock with more than 50% of capital. This is not a behavior that was seen before.

It should avoid the one stock with more than 50% of capital situation now.

I removed the day trade protection code. It simply did more harm than good.
You will have to turn on day trade protection with Robinhood.
Eventually we will get some better code for that.

I also added some code that favors stocks that have a price higher than the average for that stock.

UPDATE:
I would hold off on using this algo. I need to work on it some more. The orders being placed in live trading seem to guarantee a loss.

Clone Algorithm
1076
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.pipeline import Pipeline
from quantopian.algorithm import attach_pipeline, pipeline_output
from quantopian.pipeline.data.builtin import USEquityPricing
from quantopian.pipeline.data import morningstar
from quantopian.pipeline.factors import SimpleMovingAverage, AverageDollarVolume
from quantopian.pipeline.filters.morningstar import IsPrimaryShare

import numpy as np #needed for NaN handling

def initialize(context):
    #set_commission(commission.PerShare(cost=0.01, min_trade_cost=1.50))
    set_slippage(slippage.VolumeShareSlippage(volume_limit=.20, price_impact=0.0))
    #set_slippage(slippage.FixedSlippage(spread=0.00))
    set_commission(commission.PerTrade(cost=0.00))
    #set_slippage(slippage.FixedSlippage(spread=0.00))
    set_long_only()

    context.MyNumberOfCandidates=100
    context.MyLeastPrice=1.20
    context.MyMostPrice=1.49

    # Rebalance
    EveryThisManyMinutes=3
    TradingDayHours=6.5
    TradingDayMinutes=int((TradingDayHours*60)-(EveryThisManyMinutes*2))
    for minutez in xrange(
        EveryThisManyMinutes, 
        TradingDayMinutes, 
        EveryThisManyMinutes
    ):
        schedule_function(my_rebalance, date_rules.every_day(), time_rules.market_open(minutes=minutez))

    # Prevent excessive logging of canceled orders at market close.
    schedule_function(cancel_open_orders, date_rules.every_day(), time_rules.market_close(hours=0, minutes=1))

    # Record variables at the end of each day.
    schedule_function(my_record_vars, date_rules.every_day(), time_rules.market_close())

    # Create our pipeline and attach it to our algorithm.
    my_pipe = make_pipeline(context)
    attach_pipeline(my_pipe, 'my_pipeline')

def make_pipeline(context):
    """
    Create our pipeline.
    """

    # Filter for primary share equities. IsPrimaryShare is a built-in filter.
    primary_share = IsPrimaryShare()

    # Equities listed as common stock (as opposed to, say, preferred stock).
    # 'ST00000001' indicates common stock.
    common_stock = morningstar.share_class_reference.security_type.latest.eq('ST00000001')

    # Non-depositary receipts. Recall that the ~ operator inverts filters,
    # turning Trues into Falses and vice versa
    not_depositary = ~morningstar.share_class_reference.is_depositary_receipt.latest

    # Equities not trading over-the-counter.
    not_otc = ~morningstar.share_class_reference.exchange_id.latest.startswith('OTC')

    # Not when-issued equities.
    not_wi = ~morningstar.share_class_reference.symbol.latest.endswith('.WI')

    # Equities without LP in their name, .matches does a match using a regular
    # expression
    not_lp_name = ~morningstar.company_reference.standard_name.latest.matches('.* L[. ]?P.?$')

    # Equities with a null value in the limited_partnership Morningstar
    # fundamental field.
    not_lp_balance_sheet = morningstar.balance_sheet.limited_partnership.latest.isnull()

    # Equities whose most recent Morningstar market cap is not null have
    # fundamental data and therefore are not ETFs.
    have_market_cap = morningstar.valuation.market_cap.latest.notnull()

    # At least a certain price
    price = USEquityPricing.close.latest
    AtLeastPrice   = (price >= context.MyLeastPrice)
    AtMostPrice    = (price <= context.MyMostPrice)

    # Filter for stocks that pass all of our previous filters.
    tradeable_stocks = (
        primary_share
        & common_stock
        & not_depositary
        & not_otc
        & not_wi
        & not_lp_name
        & not_lp_balance_sheet
        & have_market_cap
        & AtLeastPrice
        & AtMostPrice
    )

    LowVar=6
    HighVar=40

    log.info('\nAlgorithm initialized variables:\n context.MyNumberOfCandidates %s \n LowVar %s \n HighVar %s'
        % (context.MyNumberOfCandidates, LowVar, HighVar)
    )

    # High dollar volume filter.
    base_universe = AverageDollarVolume(
        window_length=20,
        mask=tradeable_stocks
    ).percentile_between(LowVar, HighVar)

    # Short close price average.
    ShortAvg = SimpleMovingAverage(
        inputs=[USEquityPricing.close],
        window_length=3,
        mask=base_universe
    )

    # Long close price average.
    LongAvg = SimpleMovingAverage(
        inputs=[USEquityPricing.close],
        window_length=45,
        mask=base_universe
    )

    percent_difference = (ShortAvg - LongAvg) / LongAvg

    # Filter to select securities to long.
    stocks_worst = percent_difference.bottom(context.MyNumberOfCandidates)
    securities_to_trade = (stocks_worst)

    return Pipeline(
        columns={
            'stocks_worst': stocks_worst
        },
        screen=(securities_to_trade),
    )

def my_compute_weights(context):
    """
    Compute ordering weights.
    """
    # Compute even target weights for our long positions and short positions.
    stocks_worst_weight = 1.00/len(context.stocks_worst)

    return stocks_worst_weight

def before_trading_start(context, data):
    # Gets our pipeline output every day.
    context.output = pipeline_output('my_pipeline')

    context.stocks_worst = context.output[context.output['stocks_worst']].index.tolist()

    context.stocks_worst_weight = my_compute_weights(context)

    from itertools import cycle
    context.MyCandidate = cycle(context.stocks_worst)
    
    pass

def my_rebalance(context, data):
    BuyFactor=.9950
    SellFactor=1.33 #no worries, this gets auto reduced
    cash=context.portfolio.cash
    PositionCount=len(context.portfolio.positions)
    if 1>PositionCount:
        PositionCount=1
    PositionFactor=float(PositionCount*.005)
    LeverageFactor=float(context.account.leverage/PositionCount*5)

    cancel_open_buy_orders(context, data)

    # Order sell at profit target in hope that somebody actually buys it
    for stock in context.portfolio.positions:
        if not get_open_orders(stock):
            StockShares = context.portfolio.positions[stock].amount
            CurrPrice = float(data.current([stock], 'price'))
            CostBasis = float(context.portfolio.positions[stock].cost_basis)
            ProfitLossFactor = float(CurrPrice/CostBasis)
            MySellFactor = float((SellFactor*ProfitLossFactor)-PositionFactor-LeverageFactor)
            SellPrice = float(CostBasis*MySellFactor)
            if .75*CostBasis>SellPrice:
                SellPrice = float(.75*CostBasis)
            if np.isnan(SellPrice):
                pass # probably best to wait until nan goes away
            else:
                order(stock, -StockShares,
                    style=LimitOrder(SellPrice)
                )

    stock = context.MyCandidate.next()
    PH = data.history([stock], 'price', 45, '1d')
    PH_Avg = float(PH.mean())
    CurrPrice = float(data.current([stock], 'price'))
    if np.isnan(CurrPrice):
        pass # probably best to wait until nan goes away
    else:
        if CurrPrice > PH_Avg:
            BuyPrice=float(CurrPrice*.997)
        else:
            BuyPrice=float(CurrPrice*BuyFactor)
        LeverageFactor=float(context.account.leverage)
        if .10>LeverageFactor:
            LeverageFactor=.10
        if .75<LeverageFactor:
            LeverageFactor=1.00
        StockShares = int(LeverageFactor*cash/BuyPrice)
        order(stock, StockShares,
            style=LimitOrder(BuyPrice)
        )

def my_record_vars(context, data):
    """
    Record variables at the end of each day.
    """

    # Record our variables.
    record(leverage=context.account.leverage)
    longs = shorts = 0
    for position in context.portfolio.positions.itervalues():
        if position.amount > 0:
            longs += 1
        if position.amount < 0:
            shorts += 1
    record(long_count=longs, short_count=shorts)


def log_open_order(StockToLog):
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        if stock == StockToLog:
            for order in orders:
                message = 'Found open order for {amount} shares in {stock}'
                log.info(message.format(amount=order.amount, stock=stock))

def log_open_orders():
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        for order in orders:
            message = 'Found open order for {amount} shares in {stock}'
            log.info(message.format(amount=order.amount, stock=stock))

def cancel_open_buy_orders(context, data):
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        for order in orders:
            #message = 'Canceling order of {amount} shares in {stock}'
            #log.info(message.format(amount=order.amount, stock=stock))
            if 0<order.amount: #it is a buy order
                cancel_order(order)

def cancel_open_orders(context, data):
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        for order in orders:
            #message = 'Canceling order of {amount} shares in {stock}'
            #log.info(message.format(amount=order.amount, stock=stock))
            cancel_order(order)

# This is the every minute stuff
def handle_data(context, data):
    pass
There was a runtime error.

I think that the losses are due to market conditions. I am live paper trading this week it broke even.

For all of us attempting to learn / understand both quantopian and python, I find the following to be helpful.

print len(context.portfolio.positions), context.portfolio.positions  
PrintedResult=  
4  
printed blank line here  
{
    Equity(  
        49131,  
        symbol=u'OESX',  
        asset_name=u'ORION ENERGY SYSTEMS INC COM STK (WI)',  
        exchange=u'NASDAQ',  
        start_date=Timestamp('2015-06-12 00:00:00+0000', tz='UTC'),  
        end_date=Timestamp('2016-11-07 00:00:00+0000', tz='UTC'),  
        first_traded=None,  
        auto_close_date=Timestamp('2016-11-10 00:00:00+0000', tz='UTC'),  
        exchange_full=u'NASDAQ CAPITAL MARKET'  
    ):Position({  
        'last_sale_date': Timestamp('2016-10-27 17:37:00+0000', tz='UTC'),  
        'amount': 351,  
        'last_sale_price': 1.22,  
        'cost_basis': 1.23,  
        'sid': Equity(  
            49131,  
            symbol=u'OESX',  
            asset_name=u'ORION ENERGY SYSTEMS INC COM STK (WI)',  
            exchange=u'NASDAQ',  
            start_date=Timestamp('2015-06-12 00:00:00+0000', tz='UTC'),  
            end_date=Timestamp('2016-11-07 00:00:00+0000', tz='UTC'),  
            first_traded=None,  
            auto_close_date=Timestamp('2016-11-10 00:00:00+0000', tz='UTC'),  
            exchange_full=u'NASDAQ CAPITAL MARKET'  
        )  
    }),  
    Equity(  
        48635,  
        ...  
    ):Position({  
        ...  
        'sid': Equity(  
            48635,  
            ...  
        )  
    }),  
    ...  
}

for stock in context.portfolio.positions:  
    print stock  
PrintedResult=  
2016-10-28 07:45  PRINT Equity(49131 [OESX])  
2016-10-28 07:45  PRINT Equity(48635 [BLPH])  
2016-10-28 07:45  PRINT Equity(49452 [MIRN])  
2016-10-28 07:45  PRINT Equity(33103 [PFIE])  

making progress
look at the logs when you run it
do NOT live trade this yet, it will lose money

Clone Algorithm
1076
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.pipeline import Pipeline
from quantopian.algorithm import attach_pipeline, pipeline_output
from quantopian.pipeline.data.builtin import USEquityPricing
from quantopian.pipeline.data import morningstar
from quantopian.pipeline.factors import SimpleMovingAverage, AverageDollarVolume
from quantopian.pipeline.filters.morningstar import IsPrimaryShare

import numpy as np #needed for NaN handling

def initialize(context):
    #set_commission(commission.PerShare(cost=0.01, min_trade_cost=1.50))
    set_slippage(slippage.VolumeShareSlippage(volume_limit=.20, price_impact=0.0))
    #set_slippage(slippage.FixedSlippage(spread=0.00))
    set_commission(commission.PerTrade(cost=0.00))
    #set_slippage(slippage.FixedSlippage(spread=0.00))
    set_long_only()

    context.MinPositions=5
    context.MaxPositions=20
    context.MaxCandidates=100
    context.MyLeastPrice=1.20
    context.MyMostPrice=1.49

    # over simplistic tracking of position age
    context.age={}
    print len(context.portfolio.positions)

    # Rebalance
    EveryThisManyMinutes=3
    TradingDayHours=6.5
    TradingDayMinutes=int((TradingDayHours*60)-(EveryThisManyMinutes*2))
    for minutez in xrange(
        EveryThisManyMinutes, 
        TradingDayMinutes, 
        EveryThisManyMinutes
    ):
        schedule_function(my_rebalance, date_rules.every_day(), time_rules.market_open(minutes=minutez))

    # Prevent excessive logging of canceled orders at market close.
    schedule_function(cancel_open_orders, date_rules.every_day(), time_rules.market_close(hours=0, minutes=1))

    # Record variables at the end of each day.
    schedule_function(my_record_vars, date_rules.every_day(), time_rules.market_close())

    # Create our pipeline and attach it to our algorithm.
    my_pipe = make_pipeline(context)
    attach_pipeline(my_pipe, 'my_pipeline')

def make_pipeline(context):
    """
    Create our pipeline.
    """

    # Filter for primary share equities. IsPrimaryShare is a built-in filter.
    primary_share = IsPrimaryShare()

    # Equities listed as common stock (as opposed to, say, preferred stock).
    # 'ST00000001' indicates common stock.
    common_stock = morningstar.share_class_reference.security_type.latest.eq('ST00000001')

    # Non-depositary receipts. Recall that the ~ operator inverts filters,
    # turning Trues into Falses and vice versa
    not_depositary = ~morningstar.share_class_reference.is_depositary_receipt.latest

    # Equities not trading over-the-counter.
    not_otc = ~morningstar.share_class_reference.exchange_id.latest.startswith('OTC')

    # Not when-issued equities.
    not_wi = ~morningstar.share_class_reference.symbol.latest.endswith('.WI')

    # Equities without LP in their name, .matches does a match using a regular
    # expression
    not_lp_name = ~morningstar.company_reference.standard_name.latest.matches('.* L[. ]?P.?$')

    # Equities with a null value in the limited_partnership Morningstar
    # fundamental field.
    not_lp_balance_sheet = morningstar.balance_sheet.limited_partnership.latest.isnull()

    # Equities whose most recent Morningstar market cap is not null have
    # fundamental data and therefore are not ETFs.
    have_market_cap = morningstar.valuation.market_cap.latest.notnull()

    # At least a certain price
    price = USEquityPricing.close.latest
    AtLeastPrice   = (price >= context.MyLeastPrice)
    AtMostPrice    = (price <= context.MyMostPrice)

    # Filter for stocks that pass all of our previous filters.
    tradeable_stocks = (
        primary_share
        & common_stock
        & not_depositary
        & not_otc
        & not_wi
        & not_lp_name
        & not_lp_balance_sheet
        & have_market_cap
        & AtLeastPrice
        & AtMostPrice
    )

    LowVar=6
    HighVar=40

    log.info('\nAlgorithm initialized variables:\n context.MaxCandidates %s \n LowVar %s \n HighVar %s'
        % (context.MaxCandidates, LowVar, HighVar)
    )

    # High dollar volume filter.
    base_universe = AverageDollarVolume(
        window_length=20,
        mask=tradeable_stocks
    ).percentile_between(LowVar, HighVar)

    # Short close price average.
    ShortAvg = SimpleMovingAverage(
        inputs=[USEquityPricing.close],
        window_length=3,
        mask=base_universe
    )

    # Long close price average.
    LongAvg = SimpleMovingAverage(
        inputs=[USEquityPricing.close],
        window_length=45,
        mask=base_universe
    )

    percent_difference = (ShortAvg - LongAvg) / LongAvg

    # Filter to select securities to long.
    stocks_worst = percent_difference.bottom(context.MaxCandidates)
    securities_to_trade = (stocks_worst)

    return Pipeline(
        columns={
            'stocks_worst': stocks_worst
        },
        screen=(securities_to_trade),
    )

def my_compute_weights(context):
    """
    Compute ordering weights.
    """
    # Compute even target weights for our long positions and short positions.
    stocks_worst_weight = 1.00/len(context.stocks_worst)

    return stocks_worst_weight

def before_trading_start(context, data):
    # Gets our pipeline output every day.
    context.output = pipeline_output('my_pipeline')

    context.stocks_worst = context.output[context.output['stocks_worst']].index.tolist()

    context.stocks_worst_weight = my_compute_weights(context)

    from itertools import cycle
    context.MyCandidate = cycle(context.stocks_worst)
    
    print len(context.portfolio.positions)
    for stock in context.portfolio.positions:
        if stock in context.age:
            context.age[stock] += 1
        else:
            context.age[stock] = 1
    for stock in context.age:
        if stock not in context.portfolio.positions:
            context.age[stock] = -10
        message = 'stock.symbol: {symbol}  :  age: {age}'
        log.info(message.format(symbol=stock.symbol, age=context.age[stock]))

    pass

def my_rebalance(context, data):
    BuyFactor=.9950
    SellFactor=1.33 #no worries, this gets auto reduced
    cash=context.portfolio.cash
    PositionCount=len(context.portfolio.positions)
    if 1>PositionCount:
        PositionCount=1
    PositionFactor=float(PositionCount*.005)
    LeverageFactor=float(context.account.leverage/PositionCount*5)

    cancel_open_buy_orders(context, data)

    # Order sell at profit target in hope that somebody actually buys it
    for stock in context.portfolio.positions:
        if not get_open_orders(stock):
            StockShares = context.portfolio.positions[stock].amount
            CurrPrice = float(data.current([stock], 'price'))
            CostBasis = float(context.portfolio.positions[stock].cost_basis)
            ProfitLossFactor = float(CurrPrice/CostBasis)
            MySellFactor = float((SellFactor*ProfitLossFactor)-PositionFactor-LeverageFactor)
            SellPrice = float(CostBasis*MySellFactor)
            if .75*CostBasis>SellPrice:
                SellPrice = float(.75*CostBasis)
            if np.isnan(SellPrice):
                pass # probably best to wait until nan goes away
            else:
                order(stock, -StockShares,
                    style=LimitOrder(SellPrice)
                )

    stock = context.MyCandidate.next()
    PH = data.history([stock], 'price', 45, '1d')
    PH_Avg = float(PH.mean())
    CurrPrice = float(data.current([stock], 'price'))
    if np.isnan(CurrPrice):
        pass # probably best to wait until nan goes away
    else:
        if CurrPrice > PH_Avg:
            BuyPrice=float(CurrPrice*.997)
        else:
            BuyPrice=float(CurrPrice*BuyFactor)
        LeverageFactor=float(context.account.leverage)
        if .10>LeverageFactor:
            LeverageFactor=.10
        if .75<LeverageFactor:
            LeverageFactor=1.00
        StockShares = int(LeverageFactor*cash/BuyPrice)
        order(stock, StockShares,
            style=LimitOrder(BuyPrice)
        )

def my_record_vars(context, data):
    """
    Record variables at the end of each day.
    """

    # Record our variables.
    record(leverage=context.account.leverage)
    longs = shorts = 0
    for position in context.portfolio.positions.itervalues():
        if position.amount > 0:
            longs += 1
        if position.amount < 0:
            shorts += 1
    record(long_count=longs, short_count=shorts)


def log_open_order(StockToLog):
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        if stock == StockToLog:
            for order in orders:
                message = 'Found open order for {amount} shares in {stock}'
                log.info(message.format(amount=order.amount, stock=stock))

def log_open_orders():
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        for order in orders:
            message = 'Found open order for {amount} shares in {stock}'
            log.info(message.format(amount=order.amount, stock=stock))

def cancel_open_buy_orders(context, data):
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        for order in orders:
            #message = 'Canceling order of {amount} shares in {stock}'
            #log.info(message.format(amount=order.amount, stock=stock))
            if 0<order.amount: #it is a buy order
                cancel_order(order)

def cancel_open_orders(context, data):
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        for order in orders:
            #message = 'Canceling order of {amount} shares in {stock}'
            #log.info(message.format(amount=order.amount, stock=stock))
            cancel_order(order)

# This is the every minute stuff
def handle_data(context, data):
    pass
There was a runtime error.

Yet again, another thread has gotten "long in the tooth".

Algo has been renamed Robin Hood Extreme Vetting.

ROBINHOOD PAPER TRADING RESULTS FROM 10/14/2016 - 11/10/2016:

INITIAL CAPITAL: $1000
ENDING CAPITAL: $1089.05

PERCENT CHANGE: +8.90%
SHARPE: 3.73

LONG EXPOSURE AT THIS TIME: $363.20
AVAILABLE CASH AT THIS TIME: $725.85

Most of the earnings made on 10/25/2016, but has been consistently seeing changes well above S&P. I love this algo! Running live in robinhood as well, not enough data to return yet.

  • Something to note: Everyday when I look at the progress of this algo, one or more of the positions are down in the red, but over time it seems as though this algo has pulled through. It's actually the only algo that I've seen consistent returns on. I'm excited to see how robinhood fares, and how additional time affects performance.

If your live trading proves profitable over a month or so, then please post a backtest that has the same version of the algo that you are using. My live trading so far has mostly lost money. But I do believe there has got to be a way to make it work.

Sounds good @charles. I will make sure to follow up on my paper trading and the robinhood live trading. It may be good or bad that the market is in such turmoil right now following the elections. It will either prove how the algo runs in a volatile market, which in turn may be good or bad for future performance; it may also show faulty results poisoned by the volatility. We shall see.

Looking at the change alongside the S&P, I expect this algo to track the benchmark while keeping ahead, so it looks good for the algo.

Again, I will keep up with my progress and will keep you all in the loop! In the mean time, the algo that has made the progress listed above (also the algo that is being run LIVE, is attached below.)

  • Run a diff to be sure, but I'm pretty sure I only change the initialization to 1 minute after market open, from original 7 minutes that I retrieved from forums. 1 Minute after had better results, which I figured.
Clone Algorithm
100
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.pipeline import Pipeline
from quantopian.algorithm import attach_pipeline, pipeline_output
from quantopian.pipeline.data.builtin import USEquityPricing
from quantopian.pipeline.data import morningstar
from quantopian.pipeline.factors import SimpleMovingAverage, AverageDollarVolume
from quantopian.pipeline.filters.morningstar import IsPrimaryShare

def initialize(context):
    #set_commission(commission.PerShare(cost=0.01, min_trade_cost=1.50))
    set_slippage(slippage.VolumeShareSlippage(volume_limit=.20, price_impact=0.0))
    #set_slippage(slippage.FixedSlippage(spread=0.00))
    set_commission(commission.PerTrade(cost=0.00))
    #set_slippage(slippage.FixedSlippage(spread=0.00))
    set_long_only()

    context.PV=context.portfolio.portfolio_value
    context.NextDay=True
    context.Wait=False
    context.StartingWaitMin=50
    context.WaitMin=context.StartingWaitMin
    #context.GIWeight=.66
    context.GIWeight=1.00
    #context.SSWeight=.34
    context.SSWeight=0

    schedule_function(StopWait, date_rules.month_start(days_offset=10), time_rules.market_open(hours=0, minutes=1))

    # Record variables at the end of each day.
    schedule_function(my_record_vars, date_rules.every_day(), time_rules.market_close())

    # Create our pipeline and attach it to our algorithm.
    my_pipe = make_pipeline(context)
    attach_pipeline(my_pipe, 'my_pipeline')

def make_pipeline(context):
    """
    Create our pipeline.
    """

    # Filter for primary share equities. IsPrimaryShare is a built-in filter.
    primary_share = IsPrimaryShare()

    # Equities listed as common stock (as opposed to, say, preferred stock).
    # 'ST00000001' indicates common stock.
    common_stock = morningstar.share_class_reference.security_type.latest.eq('ST00000001')

    # Non-depositary receipts. Recall that the ~ operator inverts filters,
    # turning Trues into Falses and vice versa
    not_depositary = ~morningstar.share_class_reference.is_depositary_receipt.latest

    # Equities not trading over-the-counter.
    not_otc = ~morningstar.share_class_reference.exchange_id.latest.startswith('OTC')

    # Not when-issued equities.
    not_wi = ~morningstar.share_class_reference.symbol.latest.endswith('.WI')

    # Equities without LP in their name, .matches does a match using a regular
    # expression
    not_lp_name = ~morningstar.company_reference.standard_name.latest.matches('.* L[. ]?P.?$')

    # Equities with a null value in the limited_partnership Morningstar
    # fundamental field.
    not_lp_balance_sheet = morningstar.balance_sheet.limited_partnership.latest.isnull()

    # Equities whose most recent Morningstar market cap is not null have
    # fundamental data and therefore are not ETFs.
    have_market_cap = morningstar.valuation.market_cap.latest.notnull()

    # At least a certain price
    price = USEquityPricing.close.latest
    AtLeastPrice   = (price >= .80)
    AtMostPrice    = (price <= 3.00)

    # Filter for stocks that pass all of our previous filters.
    tradeable_stocks = (
        primary_share
        & common_stock
        & not_depositary
        & not_otc
        & not_wi
        & not_lp_name
        & not_lp_balance_sheet
        & have_market_cap
        & AtLeastPrice
        & AtMostPrice
    )

    BottomVar=10
    TopVar=10

    LowVar=6
    HighVar=40

    log.info('\nAlgorithm initialized variables:\n BottomVar %s \n TopVar %s \n LowVar %s \n HighVar %s'
        % (BottomVar, TopVar, LowVar, HighVar)
    )
    #record(BottomVar=BottomVar, TopVar=TopVar, LowVar=LowVar, HighVar=HighVar)

    # High dollar volume filter.
    base_universe = AverageDollarVolume(
        window_length=20,
        mask=tradeable_stocks
    ).percentile_between(LowVar, HighVar)

    # Short close price average.
    ShortAvg = SimpleMovingAverage(
        inputs=[USEquityPricing.close],
        window_length=3,
        mask=base_universe
    )

    # Long close price average.
    LongAvg = SimpleMovingAverage(
        inputs=[USEquityPricing.close],
        window_length=45,
        mask=base_universe
    )

    percent_difference = (ShortAvg - LongAvg) / LongAvg

    # Filter to select securities to long.
    stocks_worst = percent_difference.bottom(BottomVar)
    stocks_best = percent_difference.top(TopVar)
    securities_to_trade = (stocks_worst | stocks_best)

    return Pipeline(
        columns={
            'stocks_worst': stocks_worst,
            'stocks_best': stocks_best
        },
        screen=(securities_to_trade),
    )

def my_compute_weights(context):
    """
    Compute ordering weights.
    """
    # Compute even target weights for our long positions and short positions.
    stocks_worst_weight = context.GIWeight / len(context.stocks_worst)
    stocks_best_weight = context.SSWeight / len(context.stocks_best)

    return stocks_worst_weight, stocks_best_weight

def before_trading_start(context, data):
    context.NextDay=True

    # Gets our pipeline output every day.
    context.output = pipeline_output('my_pipeline')

    context.stocks_worst = context.output[context.output['stocks_worst']].index.tolist()
    context.stocks_best = context.output[context.output['stocks_best']].index.tolist()

    context.stocks_worst_weight, context.stocks_best_weight = my_compute_weights(context)
    pass

def my_rebalance(context, data):
    GetInFactor=.94
    SSFactor=1.06
    if context.NextDay:

        cash=context.portfolio.cash
        log.info('\n%s   Probable cash balance BEFORE rebalancing buys' % (cash))

        for stock in context.stocks_worst:
            if data.can_trade(stock):
                Curr_P = float(data.current([stock], 'price'))
                if get_open_orders(stock):
                    #log_open_order(stock)
                    continue #do NOT do anything new with this stock until the orders are filled or cancelled at end of day
                if cash >= context.stocks_worst_weight*context.portfolio.portfolio_value:
                    order_value(stock, context.stocks_worst_weight*context.portfolio.portfolio_value,
                        style=LimitOrder(Curr_P*GetInFactor)
                    )
                    cash=cash - (context.stocks_worst_weight*context.portfolio.portfolio_value)

        for stock in context.stocks_best:
            if data.can_trade(stock):
                Curr_P = float(data.current([stock], 'price'))
                if get_open_orders(stock):
                    #log_open_order(stock)
                    continue #do NOT do anything new with this stock until the orders are filled or cancelled at end of day
                if cash >= context.stocks_best_weight*context.portfolio.portfolio_value:
                    order_value(stock, -context.stocks_best_weight*context.portfolio.portfolio_value,
                        style=LimitOrder(Curr_P*SSFactor)
                    )
                    cash=cash - (context.stocks_best_weight*context.portfolio.portfolio_value)

        log.info('\n%s   Probable cash balance AFTER buys and BEFORE sells' % (cash))

        for stock in context.portfolio.positions:
            if stock not in context.stocks_worst and stock not in context.stocks_best and data.can_trade(stock):
                if get_open_orders(stock):
                    continue #do NOT do anything new with this stock until the orders are filled or cancelled at end of day
                StockShares = context.portfolio.positions[stock].amount
                Curr_P = float(data.current([stock], 'price'))
                order(stock, -StockShares,
                    style=LimitOrder(Curr_P)
                )
                #log.info('\nSELLING   %s   shares of   %s' % (StockSharesToSellNow, stock))

        context.NextDay=False

def my_record_vars(context, data):
    """
    Record variables at the end of each day.
    """

    # Record our variables.
    record(MaxPV=context.PV/context.portfolio.starting_cash, leverage=context.account.leverage)
    longs = shorts = 0
    for position in context.portfolio.positions.itervalues():
        if position.amount > 0:
            longs += 1
        if position.amount < 0:
            shorts += 1
    record(long_count=longs, short_count=shorts)


def log_open_order(StockToLog):
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        if stock == StockToLog:
            for order in orders:
                message = 'Found open order for {amount} shares in {stock}'
                log.info(message.format(amount=order.amount, stock=stock))

def log_open_orders():
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        for order in orders:
            message = 'Found open order for {amount} shares in {stock}'
            log.info(message.format(amount=order.amount, stock=stock))

def cancel_open_order(StockToCancel):
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        if stock == StockToCancel:
            for order in orders:
                #message = 'Canceling order of {amount} shares in {stock}'
                #log.info(message.format(amount=order.amount, stock=stock))
                cancel_order(order)
def cancel_open_orders():
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        for order in orders:
            #message = 'Canceling order of {amount} shares in {stock}'
            #log.info(message.format(amount=order.amount, stock=stock))
            cancel_order(order)

#Stop waiting
def StopWait(context, data):
    #The idea is to start fresh
    portfolio_value=context.portfolio.portfolio_value
    context.PV=portfolio_value
    context.Wait=False

# This is the every minute stuff
def handle_data(context, data):
    if context.WaitMin==0:
        context.WaitMin=context.StartingWaitMin

        GetOutFactor=1.25
        cash=context.portfolio.cash
        portfolio_value=context.portfolio.portfolio_value
        if portfolio_value < context.PV*.985 and context.account.leverage>=.33:
            context.Wait=True
            for stock in context.portfolio.positions:
                if data.can_trade(stock):
                    Curr_P = float(data.current([stock], 'price'))
                    if get_open_orders(stock):
                        continue #do NOT do anything new with this stock until the orders are filled or cancelled at end of day
                    if context.NextDay:
                        order_target_percent(stock, 0, style=LimitOrder(Curr_P*GetOutFactor))
            #context.GIWeight=.40
            context.GIWeight=1.00
        else:
            if portfolio_value > context.PV:
                context.PV=portfolio_value
            context.Wait=False
            #context.GIWeight+=.0006
            context.GIWeight=1.00

        # Maybe Take Profit
        if context.NextDay:
            for stock in context.portfolio.positions:
                if data.can_trade(stock):
                    Curr_P = float(data.current([stock], 'price'))
                    if context.portfolio.positions[stock].cost_basis*1.25<Curr_P:
                        if data.can_trade(stock):
                            if get_open_orders(stock):
                                cancel_open_order(stock)
                            order_target_percent(stock, 0, style=LimitOrder(Curr_P*.95))

        if not context.Wait and context.NextDay:

            # rebalance if no shares owned or if significant cash available
            if not context.portfolio.positions or (cash >= .25 * portfolio_value) :
                my_rebalance(context, data)

    if context.GIWeight < .40:
        context.GIWeight=.40
    if context.GIWeight > .66:
        context.GIWeight=.66
    context.GIWeight=1.00
    context.SSWeight=1-context.GIWeight

    context.WaitMin-=1
    if context.WaitMin<=0:
        context.WaitMin=0
There was a runtime error.

I just got an email this morning saying "line(s) 183 with the high-level message, TimeoutException: Too much time spent in handle_data and/or scheduled functions. 50 second limit exceeded." anyone know how to fix that?

Update: Using the production code outlined above, the following results have been found -- more to come in the future:
There are two live versions of the code, one a quantopian paper trading account started on 10/14/2016 at around 11AM EST, the other a robinhood trading version started on 11/14/2016 at around 4PM EST.

Quantopian Paper Process:
% Return: 16.40
Starting balance: $1000.00
Ending Balance: $1163.99
Sharpe Ratio: 3.74
Alpha: 1.16
Beta: 0.77
Scortino: 8.13
Info Ratio: 0.21
Volatility: 0.33

Robinhood Process:
% Return: 9.50
Starting balance: $384.65
Ending Balance: $421.01
Sharpe Ratio: 10.98
Alpha: 3.04
Beta: -2.15
Scortino: 86.83
Info Ratio: 0.43
Volatility: 0.19

Again these two accounts are one month apart in age, and the Paper Trading quotes are 15 minutes behind Production.

Thanks for the update Joseph. I've been following these threads closely. I plan to start live trading this algo in the January timeframe in the $6 - $20 price range.

Thank you all, for sharing the code, and sharing your advice and other ideas.

@Joseph I was using your code for a week and had pretty good results, 3% return. I was wondering if there was any way to get less rejected orders? It appears most of them have to do with the 5 cent increment rule. Thanks again for sharing.

Is the algo ready for its spotlight yet?

Delistings are on the radar on this page. Solely for experimentation, you can use the delisting code here to experiment, don't trade with delisting(), it's look-ahead. For information gathering it isn't going to hurt to see what happens, and instead there's also this code to log when delisted auto close happens, it is passive and that's fine, you can include that live.

I was messing around fascinated by an earlier version of this wondering why it works sometimes and noticed a drop of hundreds of percentage points if delists are not allowed to happen. (Edit: It's complicated though, this version has higher returns per dollar risked from less shorting.)

The assumption seems to be that delisted stocks result in a loss of profits, it seems the opposite simulated in this case alone based on the returns chart. To someone willing to obtain some stats, how often do backtest delists profit more than they would have live vs less? If well over 50% more rosy then maybe we ought to be more concerned with them. Meanwhile, some might like other changes in this code. I didn't do tweaking or test this thoroughly with different date ranges, my point was mere understanding.

Clone Algorithm
30
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.pipeline import Pipeline
from quantopian.algorithm import attach_pipeline, pipeline_output
from quantopian.pipeline.data.builtin import USEquityPricing
from quantopian.pipeline.data import morningstar as mstar
from quantopian.pipeline.factors import SimpleMovingAverage, AverageDollarVolume
from quantopian.pipeline.filters.morningstar import IsPrimaryShare

def initialize(context):
    c = context
    set_commission(commission.PerShare(cost=0.01, min_trade_cost=1.50))
    set_slippage(slippage.VolumeShareSlippage(volume_limit=.20, price_impact=0.0))
    #set_slippage(slippage.FixedSlippage(spread=0.00))

    c.pf      = c.portfolio.portfolio_value
    c.NextDay = True
    c.Wait    = False
    c.GIWeight     =  .66
    c.SSWeight     =  .34
    c.SSFactor     = 1.06
    c.GetInFactor  =  .94
    c.GetOutFactor = 1.25
    c.ProfitRatio  = 1.25
    c.ProfitOrder  =  .95
    c.StartWaitMin = 50
    c.WaitMin      = c.StartWaitMin

    schedule_function(StopWait,   date_rules.month_start(10), time_rules.market_open(minutes=7))
    #schedule_function(records,    date_rules.every_day(),     time_rules.market_close())
    schedule_function(cancel_oos, date_rules.every_day(),     time_rules.market_close())

    pipe = make_pipeline(c)
    attach_pipeline(pipe, 'pipeline')

def delisting(context, data, s):
    if not s.end_date: return 0
    elif (s.end_date - get_datetime()).days < 7:
        shares = context.portfolio.positions[s].amount
        value  = shares * data.current(s, 'price')
        log.info('{} {} value {} end date {}'.format(
          shares, s.symbol, value, s.end_date.date()))
        return 1

def balance(context, data):
    c = context
    if c.NextDay:
        cash = c.portfolio.cash

        for s in c.stocks_worst:
            if not data.can_trade(s): continue
            if get_open_orders(s):    continue
            if delisting(context, data, s): continue
            prc = data.current(s, 'price')
            if cash >= c.stocks_worst_weight * c.portfolio.portfolio_value:
                order_value(s, c.stocks_worst_weight * c.portfolio.portfolio_value,
                    style=LimitOrder(prc * c.GetInFactor)
                )
                cash -= (c.stocks_worst_weight * c.portfolio.portfolio_value)

        for s in c.stocks_best:
            if not data.can_trade(s): continue
            if get_open_orders(s):    continue
            if delisting(context, data, s): continue
            prc = data.current(s, 'price')
            if cash >= c.stocks_best_weight * c.portfolio.portfolio_value:
                order_value(s, -c.stocks_best_weight * c.portfolio.portfolio_value,
                    style=LimitOrder(prc * c.SSFactor)
                )
                cash -= (c.stocks_best_weight * c.portfolio.portfolio_value)

        for s in c.portfolio.positions:
            if s in c.stocks_worst or s in c.stocks_best: continue
            if not data.can_trade(s): continue
            if delisting(context, data, s): order_target(s, 0)
            if get_open_orders(s):    continue
            order_target(s, 0, style=LimitOrder(data.current(s, 'price')))
        c.NextDay = False

def handle_data(context, data):
    c = context
    if c.WaitMin == 0:
        c.WaitMin = c.StartWaitMin

        cash = c.portfolio.cash
        pf   = c.portfolio.portfolio_value

        if pf < c.pf * .985 and c.account.leverage >= .33:
            c.Wait = True
            if c.NextDay:
                for s in c.portfolio.positions:
                    if not data.can_trade(s): continue
                    if get_open_orders(s):    continue
                    prc = float(data.current(s, 'price'))
                    order_target_percent(s, 0, style=LimitOrder(prc * c.GetOutFactor))
            c.GIWeight = .40
        else:
            c.pf   = max(pf, c.pf)
            c.Wait = False
            c.GIWeight += .0006

        if c.NextDay:        # Maybe Take Profit
            for s in c.portfolio.positions:
                if not data.can_trade(s): continue
                prc = float(data.current(s, 'price'))
                if c.portfolio.positions[s].cost_basis * c.ProfitRatio >= prc: continue
                if get_open_orders(s): cancel_open_order(s)
                order_target_percent(s, 0, style=LimitOrder(prc * c.ProfitOrder))

        if not c.Wait and c.NextDay: # balance if no shares owned or if significant cash available
            if not c.portfolio.positions or (cash >= .25 * pf):
                balance(c, data)

    if c.GIWeight < .40: c.GIWeight = .40
    if c.GIWeight > .66: c.GIWeight = .66
    c.SSWeight = 1 - c.GIWeight

    c.WaitMin -= 1
    if c.WaitMin <= 0:
        c.WaitMin = 0

    pvr(context, data)

def make_pipeline(context):
    price = USEquityPricing.close.latest

    tradable = (
        IsPrimaryShare()
        & mstar.share_class_reference.security_type.latest.eq('ST00000001')
        & ~mstar.share_class_reference.is_depositary_receipt.latest
        & ~mstar.share_class_reference.exchange_id.latest.startswith('OTC')
        & ~mstar.share_class_reference.symbol.latest.endswith('.WI')
        & ~mstar.company_reference.standard_name.latest.matches('.* L[. ]?P.?$')
        & mstar.balance_sheet.limited_partnership.latest.isnull()
        & mstar.valuation.market_cap.latest.notnull()
        & (price < 3.00)
        & (price >  .80)
    )

    base     = AverageDollarVolume(window_length=20,mask=tradable).percentile_between(1, 40)
    ShortAvg = SimpleMovingAverage(inputs=[USEquityPricing.close],window_length=3, mask=base)
    LongAvg  = SimpleMovingAverage(inputs=[USEquityPricing.close],window_length=45,mask=base)
    percent_difference = (ShortAvg - LongAvg) / LongAvg
    stocks_worst = percent_difference.bottom( 4 )
    stocks_best  = percent_difference   .top( 15 )
    securities_to_trade = (stocks_worst | stocks_best)

    return Pipeline(
        columns = {
            'stocks_worst': stocks_worst,
            'stocks_best':  stocks_best
        },
        screen = (securities_to_trade),
    )

def before_trading_start(context, data):
    c = context
    c.NextDay = True
    c.output  = pipeline_output('pipeline')
    c.stocks_worst = c.output[c.output['stocks_worst']].index.tolist()
    c.stocks_best  = c.output[c.output['stocks_best']].index.tolist()
    c.stocks_worst_weight = context.GIWeight / len(context.stocks_worst)
    c.stocks_best_weight  = context.SSWeight / len(context.stocks_best)

def records(context, data):
    record(MaxPV = context.pf/context.portfolio.starting_cash, leverage = context.account.leverage)
    longs = shorts = 0
    for position in context.portfolio.positions.itervalues():
        if position.amount > 0: longs  += 1
        if position.amount < 0: shorts += 1
    record(long_count = longs, short_count = shorts)

def cancel_open_order(StockToCancel):
    oo = get_open_orders()
    if len(oo) == 0: return
    for s, orders in oo.iteritems():
        if s == StockToCancel:
            for order in orders:
                cancel_order(order.id)

def cancel_oos(context, data):
    oo = get_open_orders()
    for s in oo:
        for o in oo[s]: cancel_order(o.id)

def StopWait(context, data):
    context.pf   = context.portfolio.portfolio_value
    context.Wait = False

def pvr(context, data):
    ''' Custom chart and/or logging of profit_vs_risk returns and related information
    '''
    import time
    from datetime import datetime
    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:

        # You can modify this to total cash input minus any withdrawals
        manual_cash = c.portfolio.starting_cash

        c.pvr = {
            'options': {
                # # # # # # # # # #  Options  # # # # # # # # # #
                'logging'         : 0,    # Info to logging window with some new maximums

                'record_pvr'      : 1,    # Profit vs Risk returns (percentage)
                'record_pvrp'     : 0,    # PvR (p)roportional neg cash vs portfolio value
                'record_cash'     : 1,    # Cash available
                'record_max_lvrg' : 1,    # Maximum leverage encountered
                'record_risk_hi'  : 1,    # Highest risk overall
                'record_shorting' : 0,    # Total value of any shorts
                'record_max_shrt' : 0,    # Max value of shorting total
                'record_cash_low' : 0,    # Any new lowest cash level
                'record_q_return' : 0,    # Quantopian returns (percentage)
                'record_pnl'      : 1,    # Profit-n-Loss
                'record_risk'     : 0,    # Risked, max cash spent or shorts beyond longs+cash
                'record_leverage' : 0,    # Leverage (context.account.leverage)
                # # # # # # # # #  End options  # # # # # # # # #
            },
            'pvr'        : 0,      # Profit vs Risk returns based on maximum spent
            'cagr'       : 0,
            'max_lvrg'   : 0,
            'max_shrt'   : 0,
            'risk_hi'    : 0,
            'days'       : 0.0,
            'date_prv'   : '',
            'date_end'   : get_environment('end').date(),
            'cash_low'   : manual_cash,
            'cash'       : manual_cash,
            'start'      : manual_cash,
            'begin'      : time.time(),  # For run time
            'log_summary': 252,          # Summary every x days. 252/yr
            'run_str'    : '{} to {}  ${}  {} US/Eastern'.format(get_environment('start').date(), get_environment('end').date(), int(manual_cash), datetime.now(timezone('US/Eastern')).strftime("%Y-%m-%d %H:%M"))
        }
        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['log_summary'] = 1 # Every day when real money
        log.info(c.pvr['run_str'])
    p = c.pvr ; o = c.pvr['options']
    def _pvr(c):
        p['cagr'] = ((c.portfolio.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' % c.portfolio.portfolio_value, '%.0f' % (c.portfolio.portfolio_value - p['start'])))
        log.info('  Profited {} on {} activated/transacted for PvR of {}%'.format('%.0f' % c.portfolio.pnl, '%.0f' % p['risk_hi'], '%.1f' % p['pvr']))
        log.info('  QRet {} PvR {} CshLw {} MxLv {} RskHi {} MxShrt {}'.format('%.2f' % q_rtrn, '%.2f' % p['pvr'], '%.0f' % p['cash_low'], '%.2f' % p['max_lvrg'], '%.0f' % p['risk_hi'], '%.0f' % p['max_shrt']))
    def _minut():
        dt = get_datetime().astimezone(timezone('US/Eastern'))
        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 p['log_summary'] and p['days'] % p['log_summary'] == 0 and _minut() == '100':
        do_summary = 1              # Log summary every x days
    if do_summary or date == p['date_end']:
        p['cash'] = c.portfolio.cash
    elif p['cash'] == c.portfolio.cash and not o['logging']: return  # for speed

    shorts = sum([z.amount * z.last_sale_price for s, z in c.portfolio.positions.items() if z.amount < 0])
    q_rtrn       = 100 * c.portfolio.returns
    cash         = c.portfolio.cash
    new_risk_hi  = 0
    new_max_lv   = 0
    new_max_shrt = 0
    new_cash_low = 0               # To trigger logging in cash_low case
    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, p['start'] - cash * p['start'] / c.portfolio.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_cash_low = 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_max_lv = 1
        p['max_lvrg'] = c.account.leverage    # Maximum intraday leverage
        if o['record_max_lvrg']: record(MaxLv   = p['max_lvrg'])

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

    if risk > p['risk_hi']:
        new_risk_hi = 1
        p['risk_hi'] = risk                   # Highest risk overall
        if o['record_risk_hi']:  record(RiskHi  = p['risk_hi'])

    # Profit_vs_Risk returns based on max amount actually spent (risk high)
    if p['risk_hi'] != 0: # Avoid zero-divide
        p['pvr'] = 100 * (c.portfolio.portfolio_value - p['start']) / p['risk_hi']
        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(Lvrg = 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 = q_rtrn) # Quantopian returns to compare to pvr returns curve
    if o['record_pnl']:      record(PnL  = c.portfolio.portfolio_value - p['start']) # Profit|Loss

    if o['logging'] and (new_risk_hi or new_cash_low or new_max_lv or new_max_shrt):
        csh     = ' Cash '   + '%.0f' % cash
        risk    = ' Risk '   + '%.0f' % risk
        qret    = ' QRet '   + '%.1f' % q_rtrn
        shrt    = ' Shrt '   + '%.0f' % shorts
        lv      = ' Lv '     + '%.1f' % c.account.leverage
        pvr     = ' PvR '    + '%.1f' % p['pvr']
        rsk_hi  = ' RskHi '  + '%.0f' % p['risk_hi']
        csh_lw  = ' CshLw '  + '%.0f' % p['cash_low']
        mxlv    = ' MxLv '   + '%.2f' % p['max_lvrg']
        mxshrt  = ' MxShrt ' + '%.0f' % p['max_shrt']
        pnl     = ' PnL '    + '%.0f' % (c.portfolio.portfolio_value - p['start'])
        log.info('{}{}{}{}{}{}{}{}{}{}{}{}'.format(_minut(), lv, mxlv, qret, pvr, pnl, csh, csh_lw, shrt, mxshrt, risk, rsk_hi))
    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.