Hi,

The problem is in the line between 329 and 334. Basically costBasis and marketPrice is always returning zero even though it shouldn't. So "if (float(marketPrice) / max(float(costBasis),0.01)) > 1.1:" never become True. I want stocks to get out once I made 10% return. Could you please help me understand what I am missing?

Clone Algorithm

20

Loading...

There was an error loading this backtest.
Retry

Backtest from
to
with
initial capital

Cumulative performance:

Algorithm
Benchmark

Custom data:

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 |

""" This example comes from a request in the forums. The post can be found here: https://www.quantopian.com/posts/ranking-system-based-on-trading-volume-slash-shares-outstanding The request was: I am stuck trying to build a stock ranking system with two signals: 1. Trading Volume/Shares Outstanding. 2. Price of current day / Price of 60 days ago. Then rank Russell 2000 stocks every month, long the top 5%, short the bottom 5%. """ import pandas as pd import numpy as np from quantopian.algorithm import attach_pipeline, pipeline_output from quantopian.pipeline import Pipeline from quantopian.pipeline import CustomFactor from quantopian.pipeline.data.builtin import USEquityPricing from quantopian.pipeline.data import morningstar # Create custom factor #1 Trading Volume/Shares Outstanding ''' class Piotroski(CustomFactor): inputs = [ morningstar.operation_ratios.roa, morningstar.cash_flow_statement.operating_cash_flow, morningstar.cash_flow_statement.cash_flow_from_continuing_operating_activities, morningstar.operation_ratios.long_term_debt_equity_ratio, morningstar.operation_ratios.current_ratio, morningstar.valuation.shares_outstanding, morningstar.operation_ratios.gross_margin, morningstar.operation_ratios.assets_turnover, ] window_length = 252 def compute(self, today, assets, out, roa, cash_flow, cash_flow_from_ops, long_term_debt_ratio, current_ratio, shares_outstanding, gross_margin, assets_turnover): profit = ( (roa[-1] > 0).astype(int) + (cash_flow[-1] > 0).astype(int) + (roa[-1] > roa[0]).astype(int) + (cash_flow_from_ops[-1] > roa[-1]).astype(int) ) leverage = ( (long_term_debt_ratio[-1] < long_term_debt_ratio[0]).astype(int) + (current_ratio[-1] > current_ratio[0]).astype(int) + (shares_outstanding[-1] <= shares_outstanding[0]).astype(int) ) operating = ( (gross_margin[-1] > gross_margin[0]).astype(int) + (assets_turnover[-1] > assets_turnover[0]).astype(int) ) out[:] = profit + leverage + operating ''' class ROA(CustomFactor): window_length = 1 inputs = [morningstar.operation_ratios.roa] def compute(self, today, assets, out, roa): out[:] = (roa[-1] > 0).astype(int) class ROAChange(CustomFactor): window_length = 100 inputs = [morningstar.operation_ratios.roa] def compute(self, today, assets, out, roa): out[:] = (roa[-1] > roa[0]).astype(int) class CashFlow(CustomFactor): window_length = 1 inputs = [morningstar.cash_flow_statement.operating_cash_flow] def compute(self, today, assets, out, cash_flow): out[:] = (cash_flow[-1] > 0).astype(int) class CashFlowFromOps(CustomFactor): window_length = 1 inputs = [morningstar.cash_flow_statement.cash_flow_from_continuing_operating_activities, morningstar.operation_ratios.roa] def compute(self, today, assets, out, cash_flow_from_ops, roa): out[:] = (cash_flow_from_ops[-1] > roa[-1]).astype(int) class LongTermDebtRatioChange(CustomFactor): window_length = 100 inputs = [morningstar.operation_ratios.long_term_debt_equity_ratio] def compute(self, today, assets, out, long_term_debt_ratio): out[:] = (long_term_debt_ratio[-1] < long_term_debt_ratio[0]).astype(int) class CurrentDebtRatioChange(CustomFactor): window_length = 100 inputs = [morningstar.operation_ratios.current_ratio] def compute(self, today, assets, out, current_ratio): out[:] = (current_ratio[-1] > current_ratio[0]).astype(int) class SharesOutstandingChange(CustomFactor): window_length = 100 inputs = [morningstar.valuation.shares_outstanding] def compute(self, today, assets, out, shares_outstanding): out[:] = (shares_outstanding[-1] <= shares_outstanding[0]).astype(int) class GrossMarginChange(CustomFactor): window_length = 100 inputs = [morningstar.operation_ratios.gross_margin] def compute(self, today, assets, out, gross_margin): out[:] = (gross_margin[-1] > gross_margin[0]).astype(int) class AssetsTurnoverChange(CustomFactor): window_length = 100 inputs = [morningstar.operation_ratios.assets_turnover] def compute(self, today, assets, out, assets_turnover): out[:] = (assets_turnover[-1] > assets_turnover[0]).astype(int) class Factor1(CustomFactor): # Pre-declare inputs and window_length inputs = [morningstar.valuation_ratios.pe_ratio] window_length = 1 # Compute factor1 value def compute(self, today, assets, out, pe_ratio): out[:] = pe_ratio[-1] # Create custom factor #2 Price of current day / Price of 60 days ago. class Factor2(CustomFactor): # Pre-declare inputs and window_length inputs = [morningstar.balance_sheet.total_liabilities, morningstar.balance_sheet.stockholders_equity] window_length = 1 # Compute factor2 value def compute(self, today, assets, out, debt, equity): out[:] = debt[-1] /equity[-1] class Factor3(CustomFactor): # Pre-declare inputs and window_length inputs = [morningstar.balance_sheet.total_liabilities, morningstar.balance_sheet.stockholders_equity] window_length = 1 # Compute factor2 value def compute(self, today, assets, out, debt, equity): out[:] = debt[-1] class Factor4(CustomFactor): # Pre-declare inputs and window_length inputs = [morningstar.balance_sheet.total_liabilities, morningstar.balance_sheet.stockholders_equity] window_length = 1 # Compute factor2 value def compute(self, today, assets, out, debt, equity): out[:] = equity[-1] # Create custom factor to calculate a market cap based on yesterday's close # We'll use this to get the top 2000 stocks by market cap class MarketCap(CustomFactor): # Pre-declare inputs and window_length inputs = [USEquityPricing.close, morningstar.valuation.shares_outstanding] window_length = 1 # Compute market cap value def compute(self, today, assets, out, close, shares): out[:] = close[-1] * shares[-1] def initialize(context): context.long_leverage = 1.00 context.short_leverage = -1.00 context.len_long_short = 0.0 context.trading_day = None #list of purchased stocks with initial purchase dates stored context.timeSeriesData = pd.DataFrame() context.tradedates = {} context.max_days = 720 #approximately 2 years... context.positionCount = 0 context.max_buys = 30 #we can only purchase upto 30 stocks. # pipeline build pipe = Pipeline() attach_pipeline(pipe, 'ranked_2000') #add the two factors defined to the pipeline factor1 = Factor1() pipe.add(factor1, 'factor_1') factor2 = Factor2() pipe.add(factor2, 'factor_2') profit = ROA() + ROAChange() + CashFlow() + CashFlowFromOps() leverage = LongTermDebtRatioChange() + CurrentDebtRatioChange() + SharesOutstandingChange() operating = GrossMarginChange() + AssetsTurnoverChange() piotroski = profit + leverage + operating factor3 = piotroski pipe.add(factor3, 'factor_3') #factor4 = Factor4() #pipe.add(factor4, 'factor_4') # Create and apply a filter representing the top 2000 equities by MarketCap every day # This is an approximation of the Russell 2000 mkt_cap = MarketCap() top_2000 = mkt_cap.top(2000) #2000 factor_1_filter = (factor1 > 0) & (factor1 < 10.0) factor_2_filter = (factor2 > 0) & (factor2 < 0.5) factor_3_filter = (factor3 > 4) total_filter = (top_2000 & factor_1_filter & factor_2_filter & factor_3_filter) # use the combined filter to set the screen pipe.set_screen(total_filter) # Rank factor 1 and add the rank to our pipeline factor1_rank = factor1.rank(mask=total_filter) #pipe.add(factor1_rank, 'f1_rank') # Rank factor 2 and add the rank to our pipeline factor2_rank = factor2.rank(mask=total_filter) #pipe.add(factor2_rank, 'f2_rank') # Take the average of the two factor rankings, add this to the pipeline combo_raw = (factor1_rank+factor2_rank) #pipe.add(combo_raw, 'combo_raw') # Rank the combo_raw and add that to the pipeline pipe.add(combo_raw.rank(mask=total_filter), 'combo_rank') # Scedule my rebalance function schedule_function(func=rebalance, #date_rule=date_rules.month_start(days_offset=0), date_rule=date_rules.every_day(), time_rule=time_rules.market_open(hours=0,minutes=30), half_days=True) def before_trading_start(context, data): # Call pipelive_output to get the output # Note this is a dataframe where the index is the SIDs for all securities to pass my screen # and the colums are the factors which I added to the pipeline context.output = pipeline_output('ranked_2000') #there are some NaNs in factor 2, I'm removing those ranked_2000 = context.output.fillna(0) log.info("\n" + str(len(context.output))) # for future long/short =========================================================================================== # Narrow down the securities to only the top 500 & update my universe #context.len_long_short = (len(ranked_2000) - len(ranked_2000)%2) / 2 #context.long_list = ranked_2000.sort(['combo_rank'], ascending=False).iloc[:context.len_long_short] #context.short_list = ranked_2000.sort(['combo_rank'], ascending=False).iloc[-context.len_long_short:] #=================================================================================================================== #long only for now # Narrow down the securities to only the top 500 & update my universe context.len_long_short = min(len(ranked_2000), 30) context.long_list = ranked_2000.sort(['combo_rank'], ascending=False).iloc[:context.len_long_short] context.short_list = ranked_2000.sort(['combo_rank'], ascending=False).iloc[-0:] update_universe(context.long_list.index.union(context.short_list.index)) def handle_data(context, data): # Record and plot the leverage of our portfolio over time. record(leverage = context.account.leverage) record(positionCount = context.positionCount) record(openOrder = len(get_open_orders())) print "Long List" log.info("\n" + str(context.long_list.sort(['combo_rank'], ascending=True).head(10))) #print "Short List" #log.info("\n" + str(context.short_list.sort(['combo_rank'], ascending=False).head(10))) def sell(context, sid): if sid not in get_open_orders(): order_target_percent(sid, 0) del(context.tradedates[sid]) context.positionCount -= 1 # This rebalancing is called according to our schedule_function settings. def rebalance(context,data): #trading only happends every 2 years for stock in context.long_list.index: if (stock not in get_open_orders()) and context.positionCount < context.max_buys: if stock not in context.tradedates: if stock in data: long_weight = context.long_leverage / 30 #float(len(context.long_list)) log.info("ordering longs") log.info("weight is %s" % (long_weight)) order_percent(stock, long_weight) context.tradedates[stock] = get_datetime() context.positionCount += 1 for sid, tradedate in context.tradedates.items(): if (get_datetime() - tradedate).days > context.max_days: sell(context, sid) log.info("2 years out %s" % (sid.symbol)) for sid in context.portfolio.positions.items(): costBasis = context.portfolio.positions[sid].cost_basis marketPrice = context.portfolio.positions[sid].last_sale_price if (float(marketPrice) / max(float(costBasis),0.01)) > 1.1: sell(context, sid) log.info("Got 50 %s" % (sid.symbol)) ''' if (context.portfolio.positions[sid].amount > 0 ): costBasis = context.portfolio.positions[sid].cost_basis marketPrice = context.portfolio.positions[sid].last_sale_price if ((marketPrice / costBasis) > 1.5): log.info("we got there") sell(context, sid) ''' ''' for stock in context.portfolio.positions.iterkeys(): if stock not in context.long_list.index and stock not in context.short_list.index: order_target(stock, 0) ''' ''' long_weight = context.long_leverage / float(len(context.long_list)) short_weight = context.short_leverage / float(len(context.short_list)) for long_stock in context.long_list.index: if long_stock in data: log.info("ordering longs") log.info("weight is %s" % (long_weight)) order_target_percent(long_stock, long_weight) for short_stock in context.short_list.index: if short_stock in data: log.info("ordering shorts") log.info("weight is %s" % (short_weight)) order_target_percent(short_stock, short_weight) '''