def make_pipeline(): # Create a reference to our trading universe base_universe = QTradableStocksUS() # Get latest closing price close_price = USEquityPricing.close.latest # Calculate 3 day average of bull_minus_bear scores sentiment_score = SimpleMovingAverage( inputs=[stocktwits.bull_minus_bear], window_length=3, ) # Return Pipeline containing close_price and # sentiment_score that has our trading universe as screen return Pipeline(columns={ 'close_price': close_price, 'sentiment_score': sentiment_score, }, screen=base_universe)
def make_pipeline(): value = Fundamentals.ebitda.latest / Fundamentals.enterprise_value.latest favor = Fundamentals.accounts_receivable.latest porrec = Fundamentals.total_capitalization.latest bank = Fundamentals.revenue_growth.latest sale = Fundamentals.sale_of_investment.latest quality = Fundamentals.roe.latest universe = QTradableStocksUS() value_winsorized = value.winsorize(min_percentile=0.05, max_percentile=0.95) favor_winsorized = favor.winsorize(min_percentile=0.05, max_percentile=0.95) porrec_winsorized = porrec.winsorize(min_percentile=0.05, max_percentile=0.95) bank_winsorized = bank.winsorize(min_percentile=0.05, max_percentile=0.95) sale_winsorized = sale.winsorize(min_percentile=0.05, max_percentile=0.95) quality_winsorized = quality.winsorize(min_percentile=0.05, max_percentile=0.95) combined_factor = ( value_winsorized.zscore()*0.2+ quality_winsorized.zscore()*0.3+ favor_winsorized.zscore()*0.2 + porrec_winsorized.zscore()*0.05 + sale_winsorized.zscore()*0.1+ bank_winsorized.zscore()*0.05 ) longs = combined_factor.top(TOTAL_POSITIONS//2, mask=universe) shorts = combined_factor.bottom(TOTAL_POSITIONS//2, mask=universe) long_short_screen = (longs | shorts) # Create pipeline pipe = Pipeline( columns={ 'longs': longs, 'shorts': shorts, 'combined_factor': combined_factor }, screen=long_short_screen ) return pipe
def make_pipeline(): # Define universe # =============================================== value = morningstar.valuation_ratios.ev_to_ebitda.latest market_cap = morningstar.valuation.market_cap.latest > 2e9 universe = value.bottom(2*(NUM_LONG_POSITIONS + NUM_SHORT_POSITIONS), mask = (QTradableStocksUS() & market_cap)) sector = Sector(mask=universe) # sector needed to construct portfolio # =============================================== factors = make_factors() combined_alpha = None for name, f in factors.iteritems(): if combined_alpha == None: combined_alpha = f(mask=universe) else: combined_alpha = combined_alpha + f(mask=universe) longs = combined_alpha.top(NUM_LONG_POSITIONS) shorts = combined_alpha.bottom(NUM_SHORT_POSITIONS) long_short_screen = (longs | shorts) beta = 0.66*RollingLinearRegressionOfReturns( target=sid(8554), returns_length=5, regression_length=260, mask=long_short_screen ).beta + 0.33*1.0 # Create pipeline pipe = Pipeline(columns = { 'combined_alpha':combined_alpha, 'sector':sector, 'market_beta':beta }, screen = long_short_screen) return pipe
def make_pipeline(): # Set universe base_universe = QTradableStocksUS() & MarketCap().top(500) # Create the pipes/factors for each stock yesterday_close = USEquityPricing.close.latest sentiment_factor = sentiment.sentiment_signal.latest # low = # high = # price = data.history(QTradableStocksUS() & MarketCap().top(500), pipe = Pipeline( columns={ 'close': yesterday_close, 'sentiment factor': sentiment_factor # 'low': low # 'high': high # 'price': price }, screen=base_universe) return pipe
def make_pipeline(): """ A function to create our dynamic stock selector (pipeline). Documentation on pipeline can be found here: https://www.quantopian.com/help#pipeline-title """ # Base universe set to QTradableStocksUS() base_universe = QTradableStocksUS() # Sentiment score, based on a moving average of the bull minus bear factor sentiment_score = SimpleMovingAverage( inputs=[stocktwits.bull_minus_bear], window_length=3, ) pipe = Pipeline( columns={'sentiment_score': sentiment_score}, screen=(base_universe & sentiment_score.notnull()), ) return pipe
def make_pipeline(): """ Create our pipeline. """ # Base universe set to the QTradableStocksUS. base_universe = QTradableStocksUS() # 10-day close price average. mean_10 = SimpleMovingAverage( inputs=[USEquityPricing.close], window_length=10, mask=base_universe ) # 30-day close price average. mean_30 = SimpleMovingAverage( inputs=[USEquityPricing.close], window_length=30, mask=base_universe ) percent_difference = (mean_10 - mean_30) / mean_30 # Filter to select securities to short. shorts = percent_difference.top(75) # Filter to select securities to long. longs = percent_difference.bottom(75) # Filter for all securities that we want to trade. securities_to_trade = (shorts | longs) return Pipeline( columns={ 'longs': longs, 'shorts': shorts }, screen=(securities_to_trade), )
def make_pipeline(): base_universe = QTradableStocksUS() #base_universe = Q1500US() #base_universe = Q500US() yesterday_close = PrevClose() yesterday_volume = PrevVolume() dollar_volume = AverageDollarVolume(window_length=30) #ToDo この範囲を色々変えてみる. high_dollar_volume = dollar_volume.percentile_between(98, 100) pipe = Pipeline( columns={ 'yesterday_close': yesterday_close, 'yesterday_volume': yesterday_volume, 'yesterday_turnover': yesterday_close * yesterday_volume, 'dollar_volume': dollar_volume, 'high_dollar_volume': high_dollar_volume, }, screen=base_universe & high_dollar_volume, # screen = static_assets & high_dollar_volume, ) return pipe
def initialize(context): """ Called once at the start of the algorithm. """ set_slippage(slippage.FixedSlippage(spread=0.00)) set_commission(commission.PerShare(cost=0, min_trade_cost=0)) schedule_function( rebalance, TRADE_FREQ, time_rules.market_open(minutes=1), ) # Record tracking variables at the end of each day. schedule_function( record_vars, date_rules.every_day(), time_rules.market_close(), ) # Set up universe, alphas and ML pipline context.universe = QTradableStocksUS() # if you are using IsAnnouncedAcqTarget, uncomment the next line # context.universe &= IsAnnouncedAcqTarget() ml_pipeline = make_ml_pipeline( context.universe, n_forward_days=PRED_N_FORWARD_DAYS, window_length=ML_TRAINING_WINDOW, ) # Create our dynamic stock selector. attach_pipeline(ml_pipeline, 'alpha_model') # Add the risk pipeline attach_pipeline(risk_loading_pipeline(), 'risk_factors') context.past_predictions = {} context.hold_out_accuracy = 0 context.hold_out_log_loss = 0 context.hold_out_returns_spread_bps = 0
def make_pipeline(): Market_cap = morningstar.valuation.market_cap.latest base_universe = Market_cap.top(500, mask=QTradableStocksUS()) shorts = Fscore(window_length=60).bottom(100, mask=base_universe) long_universe = Market_cap.top(20, mask=base_universe) longs = Fscore(window_length=60).top(10, mask=long_universe) securities_to_trade = (shorts | longs) return Pipeline( columns={ 'longs': longs, 'shorts': shorts, 'cap': Market_cap }, screen=(securities_to_trade), )
def make_pipeline(): v1 = factset.Fundamentals.com_eq_retain_earn.latest v3 = morningstar.Fundamentals.sale_of_investment.latest v2 = Fundamentals.market_cap.latest v4 = morningstar.Fundamentals.diluted_eps_growth.latest v5 = morningstar.Fundamentals.buy_back_yield.latest #v6 = Fundamentals.value_score.latest universe = QTradableStocksUS() #value_winsorized = value.winsorize(min_percentile=0.05, max_percentile=0.95) v1_winsorized = v1.winsorize(min_percentile=0.05, max_percentile=0.95) v2_winsorized = v2.winsorize(min_percentile=0.05, max_percentile=0.95) v3_winsorized = v3.winsorize(min_percentile=0.05, max_percentile=0.95) v4_winsorized = v4.winsorize(min_percentile=0.05, max_percentile=0.95) v5_winsorized = v5.winsorize(min_percentile=0.05, max_percentile=0.95) #v6_winsorized = v6.winsorize(min_percentile=0.05, max_percentile=0.95) combined_factor = ( #value_winsorized.zscore() + v1_winsorized.zscore() * 0.2 + v2_winsorized.zscore() * 0.01 + v3_winsorized.zscore() * 0.1 + (v4_winsorized.zscore() * 0.1 * v5_winsorized.zscore() * 0.1) #v6_winsorized.zscore()*0.2 ) longs = combined_factor.top(TOTAL_POSITIONS // 2, mask=universe) shorts = combined_factor.bottom(TOTAL_POSITIONS // 2, mask=universe) long_short_screen = (longs | shorts) pipe = Pipeline(columns={ 'longs': longs, 'shorts': shorts, 'combined_factor': combined_factor }, screen=long_short_screen) return pipe
def make_pipeline(): """ A function to create our dynamic stock selector (pipeline). Documentation on pipeline can be found here: https://www.quantopian.com/help#pipeline-title """ # Base universe set to the QTradableStocksUS base_universe = QTradableStocksUS()#Q500US() base_universe = (base_universe & Q500US()) #base_universe = (base_universe & Fundamentals.market_cap.latest.top(150)) # Factor of yesterday's close price. #yesterday_close = USEquityPricing.close.latest pipe = Pipeline( columns={ #'close': yesterday_close, 'sector': Sector(), }, screen=base_universe ) return pipe
def make_pipeline( ): # --------------------------------------------------------- # Define Universe universe = QTradableStocksUS() # Get Fiundamental Data pipe = Pipeline( columns= { 'Market Cap': morningstar.valuation.market_cap.latest.quantiles(5), 'Industry': \ morningstar.asset_classification.morningstar_industry_group_code.latest, 'Financial Health': \ morningstar.asset_classification.financial_health_grade.latest, 'book_value_per_share': \ morningstar.valuation_ratios.book_value_per_share.latest, 'value_score': morningstar.Fundamentals.value_score.latest, 'net_margin': morningstar.operation_ratios.net_margin.latest, 'sector': morningstar.Fundamentals.morningstar_sector_code.latest }, screen=universe ) return pipe
def make_pipeline(): value = Fundamentals.ebit.latest / Fundamentals.enterprise_value.latest quality = Fundamentals.roe.latest positived_sentiment = (twitter_sentiment.bull_scored_messages.latest / twitter_sentiment.total_scanned_messages.latest) sentiment_3day = SimpleMovingAverage(inputs=[sentiment.sentiment_signal], window_length=3) universe = QTradableStocksUS() value_winsorized = value.winsorize(min_percentile=0.05, max_percentile=0.95) quality_winsorized = quality.winsorize(min_percentile=0.05, max_percentile=0.95) sentiment_winsorized = sentiment_3day.winsorize(min_percentile=0.05, max_percentile=0.95) combined_factor = ( value_winsorized.zscore() + quality_winsorized.zscore() + ((positived_sentiment.zscore() + sentiment_winsorized.zscore()) / 2)) longs = combined_factor.top(TOTAL_POSITIONS // 2, mask=universe) shorts = combined_factor.bottom(TOTAL_POSITIONS // 2, mask=universe) long_short_screen = (longs | shorts) pipe = Pipeline(columns={ 'longs': longs, 'shorts': shorts, 'combined_factor': combined_factor }, screen=long_short_screen) return pipe
def make_pipeline_buy(): base_universe = QTradableStocksUS() revenue_growth = morningstar.operation_ratios.revenue_growth.latest dil_eps_growth = morningstar.earnings_ratios.diluted_eps_growth.latest mktcap = morningstar.valuation.market_cap.latest # I tried optimizing this after backtesting a little # Picking stocks that show 20% revenue growth and 20% EPS growth rev_filter = revenue_growth > 0.20 eps_filter = dil_eps_growth > 0.20 # mktcap_filter = 300000000 < mktcap < 2000000000 all_filters = rev_filter & eps_filter & base_universe pipe = Pipeline( columns={ 'rev_filter' : rev_filter, 'dil_eps_growth': dil_eps_growth, 'mktcap' : mktcap }, screen=all_filters ) return pipe
def make_pipeline(): universe = QTradableStocksUS() high = Latest( inputs=[USEquityPricing.high], mask=universe, ) low = Latest( inputs=[USEquityPricing.low], mask=universe, ) diference = high - low pipe = Pipeline( columns={ 'high': high, 'low': low, 'diference': diference, }, screen=universe, ) return pipe
def make_pipeline(): # Base universe set to the QTradableStocksUS base_universe = QTradableStocksUS() # Count 10 day min mean_10 = SimpleMovingAverage( inputs=[USEquityPricing.close], window_length=10, mask=base_universe ) # Count 30 day max mean_30 = SimpleMovingAverage( inputs=[USEquityPricing.close], window_length=30, mask=base_universe ) percent_difference = (mean_10 - mean_30) / mean_30 shorts = percent_difference.top(75) longs = percent_difference.bottom(75) # use the model pipe = Pipeline( columns={ 'longs': longs, 'shorts': shorts, 'Model': Predictor( window_length=days_for_analysis ,mask=base_universe ) } ,screen = base_universe ) return pipe
def make_pipeline(context): """ A function to create our pipeline (dynamic stock selector). The pipeline is used to rank stocks based on different factors, including builtin factors, or custom factors that you can define. Documentation on pipeline can be found here: https://www.quantopian.com/help#pipeline-title """ # Filter for stocks in the QTradableStocksUS universe. For more detail, see this post: # https://www.quantopian.com/posts/working-on-our-best-universe-yet-qtradablestocksus universe = QTradableStocksUS() # Create a Returns factor with a 5-day lookback window for all # securities in our QTradableStocksUS Filter. recent_returns = Returns(window_length=context.returns_lookback, mask=universe) # Define high and low returns filters to be the bottom 10% and top 10% of # securities in the high dollar-volume group. low_returns = recent_returns.percentile_between(0,10) high_returns = recent_returns.percentile_between(90,100) # Add a filter to the pipeline such that only high-return and low-return # securities are kept. securities_to_trade = (low_returns | high_returns) # Create a pipeline object with the defined columns and screen. pipe = Pipeline( columns={ 'low_returns': low_returns, 'high_returns': high_returns, }, screen=securities_to_trade ) return pipe
def make_pipeline(): pipe = Pipeline() '''standards''' book_to_price = 1 / Latest([Fundamentals.pb_ratio]) earning_to_price = 1 / Latest([Fundamentals.pe_ratio]) #research_and_development = Latest([Fundamentals.research_and_development]) gross_dividend_payment = Latest([Fundamentals.gross_dividend_payment]) value_score = Latest([Fundamentals.value_score]) returns = Returns(inputs=[USEquityPricing.close], window_length=2) '''filter''' mask = QTradableStocksUS() mask &= Sector().eq(sector) #mask &= value_score > 70 mask &= USEquityPricing.volume.latest > 10000 '''pipeline''' pipe = Pipeline(columns={ 'Returns': returns, 'B/P': book_to_price, 'E/P': earning_to_price, 'Dividends': gross_dividend_payment, 'Value_score': value_score }, screen=mask) return pipe
def make_pipeline(): """ A function to create our dynamic stock selector (pipeline). Documentation on pipeline can be found here: https://www.quantopian.com/help#pipeline-title """ # Base universe set to the QTradableStocksUS base_universe = QTradableStocksUS() #yesterday's close price. close = USEquityPricing.close.latest #10 day simple moving average sma_10 = sma(10) #actual factor sma_10_close = -percent_change(sma_10, close).abs() pipe = Pipeline( columns={ 'sma_10_close': sma_10_close, }, screen=base_universe ) return pipe
def make_pipeline(): """ A function that creates and returns our pipeline. We break this piece of logic out into its own function to make it easier to test and modify in isolation. In particular, this function can be copy/pasted into research and run by itself. Returns ------- pipe : Pipeline Represents computation we would like to perform on the assets that make it through the pipeline screen. """ # The factors we create here are based on fundamentals data and a moving # average of sentiment data universe = QTradableStocksUS() ###################### VARIABLES ###################################### growth_score = Fundamentals_m.growth_score.latest free_cash_flow = Fundamentals_m.free_cash_flow.latest operating_cash_flow = Fundamentals_m.operating_cash_flow.latest retained_earnings = Fundamentals_m.retained_earnings.latest enterprise_value = Fundamentals_m.enterprise_value.latest dps_growth = Fundamentals_m.dps_growth.latest cash_flow_from_continuing_operating_activities = Fundamentals_m.cash_flow_from_continuing_operating_activities.latest # Desperate value = Fundamentals.ebit.latest / Fundamentals.enterprise_value.latest value_winsorized = value.winsorize(min_percentile=0.05, max_percentile=0.95) #################################################################### growth_score = growth_score.winsorize(min_percentile=0.05, max_percentile=0.95) retained_earnings = retained_earnings.winsorize(min_percentile=0.05, max_percentile=0.95) enterprise_value = enterprise_value.winsorize(min_percentile=0.05, max_percentile=0.95) dps_growth = dps_growth.winsorize(min_percentile=0.05, max_percentile=0.95) retained_earnings = retained_earnings.winsorize(min_percentile=0.05, max_percentile=0.95) free_cash_flow = free_cash_flow.winsorize(min_percentile=0.05, max_percentile=0.95) cash_flow_from_continuing_operating_activities = cash_flow_from_continuing_operating_activities.winsorize( min_percentile=0.05, max_percentile=0.95) combined_factor = ( 15 * growth_score.zscore() + 4 * free_cash_flow.zscore() + 4 * dps_growth.zscore() + 2 * operating_cash_flow.zscore() + 2 * cash_flow_from_continuing_operating_activities.zscore() + 0.5 * retained_earnings.zscore() + 0.5 * enterprise_value.zscore()) # Build Filters representing the top and bottom baskets of stocks by our # combined ranking system. We'll use these as our tradeable universe each # day. longs = combined_factor.top(TOTAL_POSITIONS // 2, mask=universe) shorts = combined_factor.bottom(TOTAL_POSITIONS // 2, mask=universe) # The final output of our pipeline should only include # the top/bottom 300 stocks by our criteria long_short_screen = (longs | shorts) # Create pipeline pipe = Pipeline(columns={ 'longs': longs, 'shorts': shorts, 'combined_factor': combined_factor }, screen=long_short_screen) return pipe
def make_pipeline(): """ A function to create our dynamic stock selector (pipeline). Documentation on pipeline can be found here: https://www.quantopian.com/help#pipeline-title """ # Base universe set to the QTradableStocksUS mask = QTradableStocksUS() & Sector().notnull() mask &= (Fundamentals.market_cap.latest > 1000000000) mask &= ( (Fundamentals.morningstar_sector_code.latest != 103) & (Fundamentals.morningstar_sector_code.latest != 207) & (Fundamentals.morningstar_sector_code.latest != 206) & (Fundamentals.morningstar_sector_code.latest != 309) & (Fundamentals.morningstar_industry_code.latest != 20533080) & (Fundamentals.morningstar_industry_code.latest != 10217033) & (Fundamentals.morningstar_industry_group_code != 10106) & (Fundamentals.morningstar_industry_group_code != 10104) ) #mask &= (Fundamentals.total_debt_equity_ratio.latest < 1.0) earnings_yield = Fundamentals.ebit.latest/Fundamentals.enterprise_value.latest EY_rank = earnings_yield.rank(ascending=False, mask=mask) roic = Fundamentals.roic.latest roic_rank = roic .rank(ascending=False, mask=mask) debt_equity = Fundamentals.total_debt_equity_ratio.latest debt_equity_rank = debt_equity.rank(ascending=True, mask=mask) # lower is better div_yield = Fundamentals.trailing_dividend_yield.latest div_rank = div_yield.rank(ascending=False, mask=mask) # higher is better gross_margin = Fundamentals.gross_margin.latest gross_margin_rank = gross_margin.rank(ascending=False, mask=mask) rnd_ocf = Fundamentals.research_and_development.latest / Fundamentals.operating_cash_flow.latest rnd_ocf_rank = rnd_ocf.rank(ascending=False, mask=mask) total_yield = Fundamentals.total_yield.latest total_yield_rank = total_yield.rank(ascending=False, mask=mask) ma50 = SimpleMovingAverage(inputs=[USEquityPricing.close], window_length=50, mask=mask) ma200 = SimpleMovingAverage(inputs=[USEquityPricing.close], window_length=200, mask=mask) mv_yield = ma50 / ma200 mv_yield_rank = mv_yield.rank(ascending=False, mask=mask) revenue_growth = Fundamentals.revenue_growth.latest revenue_growth_rank = revenue_growth.rank(ascending=False, mask=mask) mf_rank = np.sum([ EY_rank, roic_rank, # returns = 24.12%, alpha = -.09, beta = 1.3, sharpe = .47, drawdown = -27.95% debt_equity_rank, # returns = 35.45%, alpha = -.04, beta = 1.18, sharpe = .65, drawdown = -30.26% #div_rank, # returns = 30.44%, alpha = -.05, beta = 1.07, sharpe = .65, drawdown = -22.73% gross_margin_rank, rnd_ocf_rank, total_yield_rank, revenue_growth_rank, # ]) # Factor of yesterday's close price. yesterday_close = USEquityPricing.close.latest pipe = Pipeline( columns={ 'mf_rank' : mf_rank, }, screen=mask ) return pipe
def make_pipeline(): """ A function that creates and returns our pipeline. We break this piece of logic out into its own function to make it easier to test and modify in isolation. In particular, this function can be copy/pasted into research and run by itself. Returns ------- pipe : Pipeline Represents computation we would like to perform on the assets that make it through the pipeline screen. """ #1 positive_sentiment_pct = (twitter_sentiment.bull_scored_messages.latest / twitter_sentiment.total_scanned_messages.latest) #2 quarterly_sales = Fundamentals2.sales_qf.latest #3 bueno research_development = Fundamentals2.rd_exp_qf.latest #4 pPEI = Fundamentals2.ppe_impair_qf.latest #un poco mala #5 re malo :´v other_income = Fundamentals2.oper_inc_oth_qf.latest #6 un tris malo investment_income = Fundamentals2.invest_inc_qf.latest # The factors we create here are based on fundamentals data and a moving # average of sentiment data value = Fundamentals.ebit.latest / Fundamentals.enterprise_value.latest quality = Fundamentals.roe.latest sentiment_score = SimpleMovingAverage( inputs=[stocktwits.bull_minus_bear], window_length=3, ) universe = QTradableStocksUS() # We winsorize our factor values in order to lessen the impact of outliers # For more information on winsorization, please see # https://en.wikipedia.org/wiki/Winsorizing investment_income_winsorized = investment_income.winsorize( min_percentile=0.05, max_percentile=0.95) other_income_winsorized = other_income.winsorize(min_percentile=0.05, max_percentile=0.95) pPEI_winsorized = pPEI.winsorize(min_percentile=0.05, max_percentile=0.95) research_development_winsorized = research_development.winsorize( min_percentile=0.05, max_percentile=0.95) quarterly_sales_winsorized = quarterly_sales.winsorize(min_percentile=0.05, max_percentile=0.95) positive_sentiment_pct_winsorized = positive_sentiment_pct.winsorize( min_percentile=0.05, max_percentile=0.95) value_winsorized = value.winsorize(min_percentile=0.05, max_percentile=0.95) quality_winsorized = quality.winsorize(min_percentile=0.05, max_percentile=0.95) sentiment_score_winsorized = sentiment_score.winsorize(min_percentile=0.05, max_percentile=0.95) # Here we combine our winsorized factors, z-scoring them to equalize their influence combined_factor = (investment_income_winsorized.zscore() + other_income_winsorized.zscore() + pPEI_winsorized.zscore() + research_development_winsorized.zscore() + quarterly_sales_winsorized.zscore() + positive_sentiment_pct_winsorized.zscore() + value_winsorized.zscore() + quality_winsorized.zscore() + sentiment_score_winsorized.zscore()) # Build Filters representing the top and bottom baskets of stocks by our # combined ranking system. We'll use these as our tradeable universe each # day. longs = combined_factor.top(TOTAL_POSITIONS // 2, mask=universe) shorts = combined_factor.bottom(TOTAL_POSITIONS // 2, mask=universe) # The final output of our pipeline should only include # the top/bottom 300 stocks by our criteria long_short_screen = (longs | shorts) # Create pipeline pipe = Pipeline(columns={ 'positive_sentiment_pct': positive_sentiment_pct, 'longs': longs, 'shorts': shorts, 'combined_factor': combined_factor }, screen=long_short_screen) return pipe
def make_pipeline(): """ A function that creates and returns our pipeline. We break this piece of logic out into its own function to make it easier to test and modify in isolation. In particular, this function can be copy/pasted into research and run by itself. Returns ------- pipe : Pipeline Represents computation we would like to perform on the assets that make it through the pipeline screen. """ # The factors we create here are based on fundamentals data and a moving # average of sentiment data value = Fundamentals.ebit.latest / Fundamentals.enterprise_value.latest quality = Fundamentals.roe.latest foo = Fundamentals.diluted_cont_eps_growth.latest var = Fundamentals.size_score.latest aux = Fundamentals.value_score.latest res = Fundamentals.accounts_payable.latest x = Fundamentals.accumulated_depreciation.latest y = Fundamentals.book_value_per_share.latest s = Fundamentals.working_capital_per_share.latest sentiment_score = SimpleMovingAverage( inputs=[stocktwits.bull_minus_bear], window_length=3, ) universe = QTradableStocksUS() # We winsorize our factor values in order to lessen the impact of outliers # For more information on winsorization, please see # https://en.wikipedia.org/wiki/Winsorizing value_winsorized = value.winsorize(min_percentile=0.05, max_percentile=0.95) quality_winsorized = quality.winsorize(min_percentile=0.05, max_percentile=0.95) sentiment_score_winsorized = sentiment_score.winsorize(min_percentile=0.05, max_percentile=0.95) foo_winsorized = foo.winsorize(min_percentile=0.05, max_percentile=0.95) var_winsorized = var.winsorize(min_percentile=0.05, max_percentile=0.95) aux_winsorized = aux.winsorize(min_percentile=0.05, max_percentile=0.95) res_winsorized = res.winsorize(min_percentile=0.05, max_percentile=0.95) x_winsorized = x.winsorize(min_percentile=0.05, max_percentile=0.95) y_winsorized = y.winsorize(min_percentile=0.05, max_percentile=0.95) s_winsorized = s.winsorize(min_percentile=0.05, max_percentile=0.95) # Here we combine our winsorized factors, z-scoring them to equalize their influence combined_factor = (value_winsorized.zscore() + quality_winsorized.zscore() + sentiment_score_winsorized.zscore() + 0.50 * foo_winsorized.zscore() + var_winsorized.zscore() + -0.50 * aux_winsorized.zscore() - 1 / res_winsorized.zscore() + x_winsorized.zscore() + y_winsorized.zscore() - s_winsorized.zscore()) # Build Filters representing the top and bottom baskets of stocks by our # combined ranking system. We'll use these as our tradeable universe each # day. longs = combined_factor.top(TOTAL_POSITIONS // 2, mask=universe) shorts = combined_factor.bottom(TOTAL_POSITIONS // 2, mask=universe) # The final output of our pipeline should only include # the top/bottom 300 stocks by our criteria long_short_screen = (longs | shorts) # Create pipeline pipe = Pipeline(columns={ 'longs': longs, 'shorts': shorts, 'combined_factor': combined_factor }, screen=long_short_screen) return pipe
def make_pipeline(): """ A function that creates and returns our pipeline. We break this piece of logic out into its own function to make it easier to test and modify in isolation. In particular, this function can be copy/pasted into research and run by itself. Returns ------- pipe : Pipeline Represents computation we would like to perform on the assets that make it through the pipeline screen. """ # The factors we create here are based on fundamentals data and a moving # average of sentiment data value = Fundamentals.ebit.latest / Fundamentals.enterprise_value.latest quality = Fundamentals.roe.latest sentiment_score = SimpleMovingAverage( inputs=[stocktwits.bull_minus_bear], window_length=3, ) shares = Fundamentals.shares_outstanding.latest buy_back = Fundamentals.buy_back_yield.latest assets = Fundamentals.assets_turnover.latest expenses = Fundamentals.administrative_expense.latest debto = Fundamentals.debtto_assets.latest universe = QTradableStocksUS() growth = Fundamentals.equity_per_share_growth.latest # We winsorize our factor values in order to lessen the impact of outliers # For more information on winsorization, please see # https://en.wikipedia.org/wiki/Winsorizing value_winsorized = value.winsorize(min_percentile=0.05, max_percentile=0.95) quality_winsorized = quality.winsorize(min_percentile=0.05, max_percentile=0.95) sentiment_score_winsorized = sentiment_score.winsorize(min_percentile=0.05, max_percentile=0.95) shares_winsorized = shares.winsorize(min_percentile=0.05, max_percentile=0.95) buy_back_winsorized = buy_back.winsorize(min_percentile=0.05, max_percentile=0.95) assets_winsorized = assets.winsorize(min_percentile=0.05, max_percentile=0.95) expenses_winsorized = expenses.winsorize(min_percentile=0.05, max_percentile=0.95) debto_winsorized = debto.winsorize(min_percentile=0.05, max_percentile=0.95) growth_winsorized = growth.winsorize(min_percentile=0.05, max_percentile=0.95) value_weight = 0.14 quality_weight = 0.14 sentiment_score_weight = 0.14 shares_weight = 0.3 buy_back_weight = 0.16 assets_weight = 0.5 expenses_weight = 0.14 debto_weight = 0.4 growth_weight = 0.3 #weights # Here we combine our winsorized factors, z-scoring them to equalize their influence combined_factor = ( value_winsorized.zscore() * value_weight + quality_winsorized.zscore() * quality_weight + sentiment_score_winsorized.zscore() * sentiment_score_weight + shares_winsorized.zscore() * shares_weight + buy_back_winsorized.zscore() * buy_back_weight + assets_winsorized.zscore() * assets_weight + expenses_winsorized.zscore() * expenses_weight + debto_winsorized.zscore() * debto_weight + growth_winsorized.zscore() * growth_weight) # Build Filters representing the top and bottom baskets of stocks by our # combined ranking system. We'll use these as our tradeable universe each # day. longs = combined_factor.top(TOTAL_POSITIONS // 2, mask=universe) shorts = combined_factor.bottom(TOTAL_POSITIONS // 2, mask=universe) # The final output of our pipeline should only include # the top/bottom 300 stocks by our criteria long_short_screen = (longs | shorts) # Create pipeline pipe = Pipeline(columns={ 'longs': longs, 'shorts': shorts, 'combined_factor': combined_factor }, screen=long_short_screen) return pipe
def make_pipeline(): """ Defining out trading universe and alpha factor for long and short equities """ operation_margin = operation_ratios.operation_margin.latest revenue_growth = operation_ratios.revenue_growth.latest value = (Fundamentals.ebit.latest / Fundamentals.enterprise_value.latest) roe = Fundamentals.roe.latest momentum = Momentum() liquidity = Liquidity() free_cash_flows = morningstar.valuation_ratios.fcf_yield.latest earnings_yield = morningstar.valuation_ratios.earning_yield.latest # Filter for stocks that are announced acquisition target. not_announced_acq_target = ~IsAnnouncedAcqTarget() mkt_cap_filter = morningstar.valuation.market_cap.latest >= 500000000 # dividend_filter = Fundamentals.valuation_ratios.dividend_yield >= 0.02 # Our universe is made up of stocks that have a non-null factors & with market cap over 500 Million $, are not announced # acquisition targets, and are in the Q1500US. universe = ( QTradableStocksUS() # & not_near_earnings_announcement & not_announced_acq_target & earnings_yield.notnull() & free_cash_flows.notnull() & value.notnull() & roe.notnull() & mkt_cap_filter & momentum.notnull()) # combined_factor = roe*0 # for factor in factors: # combined_factor += factor.rank(mask=universe) # prediction_rank_quantiles = prediction_quality.quantiles(5) # longs = prediction_rank_quantiles.eq(4) # shorts = prediction_rank_quantiles.eq(0) combined_factor = ( earnings_yield.winsorize(min_percentile=0.05, max_percentile=0.95).zscore(mask=universe) + free_cash_flows.winsorize(min_percentile=0.05, max_percentile=0.95).zscore(mask=universe) + value.winsorize(min_percentile=0.05, max_percentile=0.95).zscore(mask=universe) + roe.winsorize(min_percentile=0.05, max_percentile=0.95).zscore(mask=universe) + momentum.winsorize(min_percentile=0.05, max_percentile=0.95).zscore(mask=universe)) combined_factor_quantiles = combined_factor.quantiles(10) longs = combined_factor_quantiles.eq(9) shorts = combined_factor_quantiles.eq(0) # longs = combined_factor.top(2*TOTAL_POSITIONS//3, mask=universe) # shorts = combined_factor.bottom(TOTAL_POSITIONS//3, mask=universe) # We will take market beta into consideration when placing orders in our algorithm. beta = RollingLinearRegressionOfReturns(target=sid(8554), returns_length=5, regression_length=260, mask=(longs | shorts)).beta # I calculated the market beta using rolling window regression using Bloomberg's computation. # Ref: https://guides.lib.byu.edu/c.php?g=216390&p=1428678 bb_beta = (0.66 * beta) + (0.33 * 1.0) ## create pipeline columns = { 'longs': longs, 'shorts': shorts, 'market_beta': bb_beta, 'sector': Sector(), 'combined_factor': combined_factor, } pipe = Pipeline(columns=columns, screen=(longs | shorts)) return pipe
def make_pipeline(): # Ganancias por acción con frecuencia semestral reportada mas recientemente profits = fe.Actuals.slice('EPS', 'qf', 0).actual_value.latest # Estimación de ganancias por acción con frecuencia trimentral profits_estimation = fe.PeriodicConsensus.slice('EPS', 'qf', 0).mean.latest # Diferencia entre el valor real y el estimado difference_profits = (profits - profits_estimation) / profits_estimation # Flujo de caja por acción con frecuencia semestral reportada mas recientemente flow = fe.Actuals.slice('CFPS', 'qf', 0).actual_value.latest # Flujo de caja por acción con frecuencia trimentral flow_estimation = fe.PeriodicConsensus.slice('CFPS', 'qf', 0).mean.latest # Diferencia entre el valor real y el estimado difference_flow = (flow - flow_estimation) / flow_estimation # Precio de cierre close = EquityPricing.close.latest # Precio de apertura open = EquityPricing.open.latest # Diferencia entre el precio de apretura y de cierre difference_open_close_price = (close - open) / open # Precio mas alto high = EquityPricing.high.latest # Precio mas bajo low = EquityPricing.low.latest # diferencia entre el precio mas alto y el mas bajo difference_high_low_price = (high - low) / low # N° acciones negociadas volume = EquityPricing.volume.latest # factores basado en datos de fundamentals y SimpleMovingAverage value = Fundamentals.ebit.latest / Fundamentals.market_cap.latest quality = Fundamentals.roe.latest sentiment_score = SimpleMovingAverage( inputs=[stocktwits.bull_minus_bear], window_length=3, ) # Obtener universo de acciones negociables universe = QTradableStocksUS() # Cambiar los valores por fuera de los percentiles minimo y maximo por el valor del percentil del extremo correspondiente difference_profits_winsorized = -difference_profits.winsorize( min_percentile=0.05, max_percentile=0.95) difference_flow_winsorized = -difference_flow.winsorize( min_percentile=0.05, max_percentile=0.95) difference_open_close_price_winsorized = -difference_open_close_price.winsorize( min_percentile=0.05, max_percentile=0.95) difference_high_low_price_winsorized = -difference_high_low_price.winsorize( min_percentile=0.05, max_percentile=0.95) volume_winsorized = -volume.winsorize(min_percentile=0.05, max_percentile=0.95) value_winsorized = -value.winsorize(min_percentile=0.05, max_percentile=0.95) quality_winsorized = -quality.winsorize(min_percentile=0.05, max_percentile=0.95) sentiment_score_winsorized = -sentiment_score.winsorize( min_percentile=0.05, max_percentile=0.95) # Normalizar los datos y sumarlos para amplificar combined_factor = (difference_profits_winsorized.zscore() + difference_flow_winsorized.zscore() + difference_open_close_price_winsorized.zscore() + difference_high_low_price_winsorized.zscore() + volume_winsorized.zscore() + value_winsorized.zscore() + quality_winsorized.zscore() + sentiment_score_winsorized.zscore()) # Filtrar los primeros y los ultimos valores longs = combined_factor.top(TOTAL_POSITIONS // 2, mask=universe) shorts = combined_factor.bottom(TOTAL_POSITIONS // 2, mask=universe) # Unir los primeros y los ultimos valores long_short_screen = (longs | shorts) # Crear tuberia pipe = Pipeline(columns={ 'longs': longs, 'shorts': shorts, 'combined_factor': combined_factor }, screen=long_short_screen) return pipe
def make_pipeline(): value = Fundamentals.ebit.latest / Fundamentals.enterprise_value.latest quality = Fundamentals.roe.latest total_revenue = Fundamentals.total_revenue.latest yesterday_close = EquityPricing.close.latest yesterday_volume = EquityPricing.volume.latest working_capital_per_share = Fundamentals.working_capital_per_share.latest forward_dividend_yield = Fundamentals.forward_dividend_yield.latest peg_ratio = Fundamentals.peg_ratio.latest trailing_dividend_yield = Fundamentals.trailing_dividend_yield.latest sentiment_score = SimpleMovingAverage(inputs=[stocktwits.bull_minus_bear], window_length=2) test_sentiment = (twitter_sentiment.bull_scored_messages.latest / twitter_sentiment.total_scanned_messages.latest) universe = QTradableStocksUS() #----------------------------------------------------------------- recent_returns = Returns(window_length=RETURNS_LOOKBACK_DAYS, mask=universe) recent_returns_zscore = recent_returns.zscore() #---------------------------------------------------------------- value_winsorized = value.winsorize(min_percentile=0.10, max_percentile=0.90) quality_winsorized = quality.winsorize(min_percentile=0.10, max_percentile=0.90) total_revenue_winsorized = total_revenue.winsorize(min_percentile=0.10, max_percentile=0.90) yesterday_close_winsorized = yesterday_close.winsorize(min_percentile=0.10, max_percentile=0.90) yesterday_volume_winsorized = yesterday_volume.winsorize( min_percentile=0.10, max_percentile=0.90) working_capital_per_share_winsorized = working_capital_per_share.winsorize( min_percentile=0.10, max_percentile=0.90) forward_dividend_yield_winsorized = forward_dividend_yield.winsorize( min_percentile=0.10, max_percentile=0.90) peg_ratio_winsorized = peg_ratio.winsorize(min_percentile=0.10, max_percentile=0.90) trailing_dividend_yield_winsorized = trailing_dividend_yield.winsorize( min_percentile=0.10, max_percentile=0.90) sentiment_score_winsorized = sentiment_score.winsorize(min_percentile=0.10, max_percentile=0.90) #--------------------------------------------------------------- combined_factor = ( value_winsorized.zscore() + quality_winsorized.zscore() + total_revenue_winsorized.zscore() + yesterday_volume_winsorized.zscore() + working_capital_per_share_winsorized.zscore() * 2 + forward_dividend_yield_winsorized.zscore() * 2 + peg_ratio_winsorized.zscore() * 2 + trailing_dividend_yield_winsorized.zscore() + ((sentiment_score_winsorized.zscore() + test_sentiment.zscore()) / 2)) #--------------------------------------------------------------- longs = combined_factor.top(TOTAL_POSITIONS // 2, mask=universe) shorts = combined_factor.bottom(TOTAL_POSITIONS // 2, mask=universe) long_short_screen = (longs | shorts) pipe = Pipeline(columns={ 'longs': longs, 'shorts': shorts, 'recent_returns_zscore': recent_returns_zscore, 'combined_factor': combined_factor, 'total_revenue': total_revenue, 'close': yesterday_close, 'volume': yesterday_volume, }, screen=long_short_screen) return pipe
def make_pipeline(): # The factors we create here are based on fundamentals data and a moving # average of sentiment data value = Fundamentals.ebit.latest / Fundamentals.enterprise_value.latest quality = Fundamentals.roe.latest sentiment_score = SimpleMovingAverage( inputs=[stocktwits.bull_minus_bear], window_length=50, ) growth_score = Fundamentals.growth_score.latest opt_income = Fundamentals.operation_income_growth.latest market_cap = Fundamentals.market_cap.latest universe = QTradableStocksUS() # We winsorize our factor values in order to lessen the impact of outliers # For more information on winsorization, please see # https://en.wikipedia.org/wiki/Winsorizing value_winsorized = value.winsorize(min_percentile=0.05, max_percentile=0.95) quality_winsorized = quality.winsorize(min_percentile=0.05, max_percentile=0.95) sentiment_score_winsorized = sentiment_score.winsorize(min_percentile=0.05, max_percentile=0.95) growth_score_winsorized = growth_score.winsorize(min_percentile=0.05, max_percentile=0.95) opt_income_winsorized = opt_income.winsorize(min_percentile=0.05, max_percentile=0.95) market_cap_winsorized = market_cap.winsorize(min_percentile=0.05, max_percentile=0.95) combined_factor = ((1 * value_winsorized + 1 * quality_winsorized + 2 * sentiment_score_winsorized + 4 * growth_score_winsorized + 0.5 * opt_income_winsorized + 0.5 * market_cap_winsorized)) # Build Filters representing the top and bottom baskets of stocks by our # combined ranking system. We'll use these as our tradeable universe each # day. longs = combined_factor.top(TOTAL_POSITIONS // 2, mask=universe) shorts = combined_factor.bottom(TOTAL_POSITIONS // 2, mask=universe) # The final output of our pipeline should only include # the top/bottom 300 stocks by our criteria long_short_screen = (longs | shorts) # Create pipeline pipe = Pipeline(columns={ 'longs': longs, 'shorts': shorts, 'combined_factor': combined_factor }, screen=long_short_screen) return pipe
def make_pipeline(): """ A function that creates and returns our pipeline. We break this piece of logic out into its own function to make it easier to test and modify in isolation. In particular, this function can be copy/pasted into research and run by itself. Returns ------- pipe : Pipeline Represents computation we would like to perform on the assets that make it through the pipeline screen. """ # The factors we create here are based on fundamentals data and a moving # average of sentiment data value = Fundamentals.ebit.latest / Fundamentals.enterprise_value.latest quality = Fundamentals.roe.latest growth = Fundamentals.growth_score.latest accountsreceivable = Fundamentals.accounts_receivable.latest additionalcapital = Fundamentals.additional_paid_in_capital.latest capitalstock = Fundamentals.capital_stock.latest currentassets = Fundamentals.total_assets.latest currentdebt = Fundamentals.total_debt.latest dilutedgrowth = Fundamentals.equity_per_share_growth.latest dilutedepsgrowth = Fundamentals.diluted_eps_growth.latest dilutedcontepsgrowth = Fundamentals.diluted_cont_eps_growth.latest cashfinancingactivities = Fundamentals.cash_flow_from_continuing_financing_activities.latest cashinvestingactivities = Fundamentals.cash_flow_from_continuing_investing_activities.latest cashoperatingactivities = Fundamentals.cash_flow_from_continuing_operating_activities.latest changeinventory = Fundamentals.change_in_inventory.latest sentiment_score = SimpleMovingAverage( inputs=[stocktwits.bull_minus_bear], window_length=3, ) universe = QTradableStocksUS() # We winsorize our factor values in order to lessen the impact of outliers # For more information on winsorization, please see # https://en.wikipedia.org/wiki/Winsorizing value_winsorized = value.winsorize(min_percentile=0.05, max_percentile=0.95) quality_winsorized = quality.winsorize(min_percentile=0.05, max_percentile=0.95) sentiment_score_winsorized = sentiment_score.winsorize(min_percentile=0.05, max_percentile=0.95) growth_winsorized = growth.winsorize(min_percentile=0.05, max_percentile=0.95) accounts_receivable_winsorized = accountsreceivable.winsorize( min_percentile=0.05, max_percentile=0.95) additional_capital_winsorized = additionalcapital.winsorize( min_percentile=0.05, max_percentile=0.95) capital_stock_winsorized = capitalstock.winsorize(min_percentile=0.05, max_percentile=0.95) current_assets_winsorized = currentassets.winsorize(min_percentile=0.05, max_percentile=0.95) current_debt_winsorized = currentdebt.winsorize(min_percentile=0.05, max_percentile=0.95) diluted_growth_winsorized = dilutedgrowth.winsorize(min_percentile=0.05, max_percentile=0.95) diluted_eps_growth_winsorized = dilutedepsgrowth.winsorize( min_percentile=0.05, max_percentile=0.95) diluted_cont_eps_growth_winsorized = dilutedcontepsgrowth.winsorize( min_percentile=0.05, max_percentile=0.95) cash_financing_activities_winsorized = cashfinancingactivities.winsorize( min_percentile=0.05, max_percentile=0.95) cash_investing_activities_winsorized = cashinvestingactivities.winsorize( min_percentile=0.05, max_percentile=0.95) cash_operating_activities_winsorized = cashoperatingactivities.winsorize( min_percentile=0.05, max_percentile=0.95) change_in_inventory_winsorized = changeinventory.winsorize( min_percentile=0.05, max_percentile=0.95) # Here we combine our winsorized factors, z-scoring them to equalize their influence combined_factor = ( value_winsorized.zscore() + quality_winsorized.zscore() + sentiment_score_winsorized.zscore() + growth_winsorized.zscore() + accounts_receivable_winsorized.zscore() + additional_capital_winsorized.zscore() + capital_stock_winsorized.zscore() + current_assets_winsorized.zscore() - current_debt_winsorized.zscore() + diluted_growth_winsorized.zscore() - diluted_eps_growth_winsorized.zscore() - diluted_cont_eps_growth_winsorized.zscore() + cash_financing_activities_winsorized.zscore() + cash_investing_activities_winsorized.zscore() + cash_operating_activities_winsorized.zscore() + change_in_inventory_winsorized.zscore()) # Build Filters representing the top and bottom baskets of stocks by our # combined ranking system. We'll use these as our tradeable universe each # day. longs = combined_factor.top(TOTAL_POSITIONS // 2, mask=universe) shorts = combined_factor.bottom(TOTAL_POSITIONS // 2, mask=universe) # The final output of our pipeline should only include # the top/bottom 300 stocks by our criteria long_short_screen = (longs | shorts) # Create pipeline pipe = Pipeline(columns={ 'longs': longs, 'shorts': shorts, 'combined_factor': combined_factor }, screen=long_short_screen) return pipe
def make_pipeline(): """ A function that creates and returns our pipeline. We break this piece of logic out into its own function to make it easier to test and modify in isolation. In particular, this function can be copy/pasted into research and run by itself. Returns ------- pipe : Pipeline Represents computation we would like to perform on the assets that make it through the pipeline screen. """ # The factors we create here are based on fundamentals data and a moving # average of sentiment data value = Fundamentals.ebit.latest / Fundamentals.enterprise_value.latest quality = Fundamentals.roe.latest sentiment_score = SimpleMovingAverage( inputs=[stocktwits.bull_minus_bear], window_length=3, ) ebitda = Fundamentals.ebitda admin_expense = Fundamentals.administrative_expense short_liabi = fFundamentals.liabs_curr coverRatio = ebitda.latest / (admin_expense.latest + short_liabi.latest) dif_twitter = aggregated_twitter_withretweets_stocktwits.bull_minus_bear totalmessages = aggregated_twitter_withretweets_stocktwits.total_scanned_messages ratio = dif_twitter.latest / totalmessages.latest universe = QTradableStocksUS() # We winsorize our factor values in order to lessen the impact of outliers # For more information on winsorization, please see # https://en.wikipedia.org/wiki/Winsorizing value_winsorized = value.winsorize(min_percentile=0.05, max_percentile=0.95) quality_winsorized = quality.winsorize(min_percentile=0.05, max_percentile=0.95) sentiment_score_winsorized = sentiment_score.winsorize(min_percentile=0.05, max_percentile=0.95) coverRatio_winsorized = coverRatio.winsorize(min_percentile=0.05, max_percentile=0.95) ratio_winsorized = ratio.winsorize(min_percentile=0.05, max_percentile=0.95) goodw = fFundamentals.gw_impair_qf.latest goodw_winsorized = goodw.winsorize(min_percentile=0.05, max_percentile=0.95) # Here we combine our winsorized factors, z-scoring them to equalize their influence combined_factor = (value_winsorized.zscore() + quality_winsorized.zscore() + sentiment_score_winsorized.zscore() + coverRatio_winsorized.zscore() + ratio_winsorized + goodw_winsorized) # Build Filters representing the top and bottom baskets of stocks by our # combined ranking system. We'll use these as our tradeable universe each # day. longs = combined_factor.top(TOTAL_POSITIONS // 2, mask=universe) shorts = combined_factor.bottom(TOTAL_POSITIONS // 2, mask=universe) # The final output of our pipeline should only include # the top/bottom 300 stocks by our criteria long_short_screen = (longs | shorts) # Create pipeline pipe = Pipeline(columns={ 'longs': longs, 'shorts': shorts, 'combined_factor': combined_factor }, screen=long_short_screen) return pipe