def make_pipeline(): value = Fundamentals.ebit.latest / Fundamentals.enterprise_value.latest quality = Fundamentals.roe.latest sentiment_score = SimpleMovingAverage(inputs=[stocktwits.bull_minus_bear],window_length=3,) twitter_score = SimpleMovingAverage(inputs=[twitter_withretweets.bull_bear_msg_ratio],window_length=3,) news_score = SimpleMovingAverage(inputs=[sentiment.sentiment_signal], window_length=5) total_revenue = Fundamentals.total_revenue.latest growth = Fundamentals.sustainable_growth_rate.latest operation_margin = Fundamentals.operation_margin.latest net_margin = Fundamentals.net_margin.latest rec_corredor = SimpleMovingAverage( inputs = [ConsensusRecommendations.total], window_length=3, ) universe = QTradableStocksUS() value_winsorized = value.winsorize(min_percentile=0.17, max_percentile=0.83) quality_winsorized = quality.winsorize(min_percentile=0.17, max_percentile=0.83) sentiment_score_winsorized = sentiment_score.winsorize(min_percentile=0.17, max_percentile=0.83) twitter_score_winsorized = twitter_score.winsorize(min_percentile=0.17, max_percentile=0.83) news_score_winsorized = news_score.winsorize(min_percentile=0.17, max_percentile=0.83) total_revenue_winsorized = total_revenue.winsorize(min_percentile=0.17, max_percentile=0.83) growth_winsorized = growth.winsorize(min_percentile=0.17, max_percentile=0.83) operation_margin_winsorized = operation_margin.winsorize(min_percentile=0.17, max_percentile=0.83) net_margin_winsorized = net_margin.winsorize(min_percentile=0.17, max_percentile=0.83) rec_corredor_winsorized = rec_corredor.winsorize(min_percentile=0.17, max_percentile=0.83) combined_factor = ( 1*value_winsorized.zscore() + 6*quality_winsorized.zscore() + 1*sentiment_score_winsorized.zscore() + 5*twitter_score_winsorized.zscore() + 1*news_score_winsorized.zscore() + 6*growth_winsorized.zscore() + 1*operation_margin_winsorized.zscore() + 1*net_margin_winsorized.zscore() + 6*total_revenue_winsorized.zscore() + 9*rec_corredor_winsorized.zscore() ) 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(): #Predefined Factors value = Fundamentals.ebit.latest / Fundamentals.enterprise_value.latest quality = Fundamentals.roe.latest sentiment_score = SimpleMovingAverage( inputs=[stocktwits.bull_minus_bear], window_length=3, ) 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) # New Factors total_revenue = Fundamentals.total_revenue.latest mean_sentiment_5day = SimpleMovingAverage( inputs=[sentiment.sentiment_signal], window_length=5) mean_sentiment_5day_winsorized = mean_sentiment_5day.winsorize( min_percentile=0.05, max_percentile=0.95) operation_ratios_latest = operation_ratios.roic.latest valuation_ratios_dividend_yield_latest = valuation_ratios.dividend_yield.latest valuation_ratios_cash_return_latest = valuation_ratios.cash_return.latest universe = (QTradableStocksUS() & operation_ratios_latest.notnull() & valuation_ratios_dividend_yield_latest.notnull() & valuation_ratios_cash_return_latest.notnull()) operation_ratios_latest = operation_ratios_latest.rank(mask=universe, method='average') valuation_ratios_dividend_yield_latest = valuation_ratios_dividend_yield_latest.rank( mask=universe, method='average') valuation_ratios_cash_return_latest = valuation_ratios_cash_return_latest.rank( mask=universe, method='average') combined_factor = ( #Original 3 * value_winsorized.zscore() + quality_winsorized.zscore() + sentiment_score_winsorized.zscore() + #New operation_ratios_latest + valuation_ratios_dividend_yield_latest + 3 * valuation_ratios_cash_return_latest + 0.5 * mean_sentiment_5day_winsorized + 3 * total_revenue) 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(): # 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) sma50 = SimpleMovingAverage(inputs=[USEquityPricing.close], window_length=50) sma200 = SimpleMovingAverage(inputs=[USEquityPricing.close], window_length=200) smaScore = sma50/sma200 sizeScore = SimpleMovingAverage(inputs=[Fundamentals.size_score],window_length=3) growthScore = SimpleMovingAverage(inputs=[Fundamentals.growth_score],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) smaScore_winsorized =smaScore.winsorize(min_percentile=0.05, max_percentile=0.95) sizeScore_winsorized = sizeScore.winsorize(min_percentile=0.05, max_percentile=0.95) growthScore_winsorized = growthScore.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() + smaScore_winsorized.zscore() + sizeScore_winsorized.zscore() + growthScore_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(): value = Fundamentals.ebit.latest / Fundamentals.enterprise_value.latest quality = Fundamentals.roe.latest sentiment_score = SimpleMovingAverage( inputs=[stocktwits.bull_minus_bear], window_length=3, ) rec_corredor = SimpleMovingAverage( inputs=[ConsensusRecommendations.total], window_length=3, ) add_insider_transaction = SimpleMovingAverage( inputs=[ Form3AggregatedTrades.slice(False, 90).num_unique_filers.latest ], window_length=1, ) 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_score_winsorized = sentiment_score.winsorize(min_percentile=0.05, max_percentile=0.95) rec_corredor_winsorized = rec_corredor.winsorize(min_percentile=0.05, max_percentile=0.95) add_insider_transaction_winsorized = add_insider_transaction.winsorize( min_percentile=0.05, max_percentile=0.95) combined_factor = (1 * value_winsorized.zscore() + 1 * quality_winsorized.zscore() + 1 * sentiment_score_winsorized.zscore() + 9 * rec_corredor_winsorized.zscore() + 1 * add_insider_transaction_winsorized.zscore()) 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(): # The factors we create here are based on fundamentals data and a moving # average of sentiment data value = Fundamentals.ebitda.latest / Fundamentals.enterprise_value.latest quality = Fundamentals.roe.latest #Puntaje para Stocktwits sentiment_score = SimpleMovingAverage(inputs=[stocktwits.bull_minus_bear],window_length=3,) #Puntaje para twitter twitter_score = SimpleMovingAverage(inputs=[twitter_withretweets.bull_bear_msg_ratio],window_length=3,) #Puntaje noticias news_score = SimpleMovingAverage(inputs=[sentiment.sentiment_signal], window_length=5) universe = QTradableStocksUS() # We winsorize our factor values in order to lessen the impact of outliers 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) twitter_score_winsorized = twitter_score.winsorize(min_percentile=0.05, max_percentile=0.95) news_score_winsorized = news_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 = ( 3*value_winsorized.zscore() + 3*quality_winsorized.zscore() + 2*sentiment_score_winsorized.zscore() + twitter_score_winsorized.zscore() + 2*news_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={ '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, ) 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) # 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() ) # 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 quality = Fundamentals.roe.latest sentiment_score = SimpleMovingAverage( inputs=[stocktwits.bull_minus_bear], window_length=3, ) total_revenue = Fundamentals.total_revenue.latest positive_sentiment_pct = ( twitter_sentiment.bull_scored_messages.latest / twitter_sentiment.total_scanned_messages.latest ) positive_sentiment_pctt = ( twitter_sentiment2.bull_scored_messages.latest / twitter_sentiment2.total_scanned_messages.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) total_revenue_winsorized = total_revenue.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) positive_sentiment_pctt_winsorized = positive_sentiment_pctt.winsorize(min_percentile=0.05, max_percentile=0.95) # Here we combine our winsorized factors, z-scoring them to equalize their influence combined_factor = ( 0.2*value_winsorized.zscore() + 0.2*quality_winsorized.zscore() + 0.2*sentiment_score_winsorized.zscore()+ 0.2*total_revenue_winsorized.zscore()+ 0.1*positive_sentiment_pct_winsorized+ 0.1*positive_sentiment_pctt_winsorized )
def make_pipeline(): #Example Variables value = Fundamentals.ebit.latest / Fundamentals.enterprise_value.latest quality = Fundamentals.roe.latest sentiment_score = SimpleMovingAverage( inputs=[stocktwits.bull_minus_bear], window_length=3, ) #Aditional Variables fcf_ratio = Fundamentals.fcf_ratio.latest roa = Fundamentals.roa.latest accounts_receivable = Fundamentals.accounts_receivable.latest gain_loss_on_sale_of_ppe = Fundamentals.gain_loss_on_sale_of_ppe.latest universe = QTradableStocksUS() #Eliminamos los valores atipicos de las distribuciones 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) fcf_ratio_winsorized = fcf_ratio.winsorize(min_percentile=0.05, max_percentile=0.95) roa_winsorized = roa.winsorize(min_percentile=0.05, max_percentile=0.95) accounts_receivable_winsorized = accounts_receivable.winsorize( min_percentile=0.05, max_percentile=0.95) gain_loss_on_sale_of_ppe_winsorized = gain_loss_on_sale_of_ppe.winsorize( min_percentile=0.05, max_percentile=0.95) # Aqui hacemos la combinacion y asignamos pesos combined_factor = (value_winsorized.zscore() * 0.1 + quality_winsorized.zscore() * 0.1 + sentiment_score_winsorized.zscore() * 0.2 + fcf_ratio_winsorized.zscore() * 0.1 + roa_winsorized.zscore() * 0.1 + accounts_receivable_winsorized.zscore() * 0.2 + gain_loss_on_sale_of_ppe_winsorized.zscore() * 0.2) #Vamos escoger en cuales vamos en largo y cuales vamos en corto 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(): global value global quality global sentiment_score global test_sentiment global total_revenue global yesterday_close global yesterday_volume value = Fundamentals.ebit.latest / Fundamentals.enterprise_value.latest quality = Fundamentals.roe.latest sentiment_score = SimpleMovingAverage( inputs=[stocktwits.bull_minus_bear], window_length=3, ) sentiment_score = SimpleMovingAverage( inputs=[stocktwits.bull_minus_bear], window_length=3, ) test_sentiment = (twitter_sentiment.bull_scored_messages.latest / twitter_sentiment.total_scanned_messages.latest) total_revenue = Fundamentals.total_revenue.latest yesterday_close = EquityPricing.close.latest yesterday_volume = EquityPricing.volume.latest 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_score_winsorized = sentiment_score.winsorize(min_percentile=0.05, max_percentile=0.95) combined_factor = (value_winsorized.zscore() + quality_winsorized.zscore() + sentiment_score_winsorized.zscore()) 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(): returns = (-1) * Returns(window_length = 21) value = Fundamentals.ebit.latest / Fundamentals.enterprise_value.latest quality = Fundamentals.roe.latest sentiment_score = SimpleMovingAverage( inputs=[stocktwits.bull_minus_bear], window_length=21, ) ty = Fundamentals.total_yield.latest wps = Fundamentals.working_capital_per_share.latest epst = Fundamentals.tangible_book_value_per_share.latest eps = (epst-wps) * (-1) 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_score_winsorized = sentiment_score.winsorize(min_percentile=0.05, max_percentile=0.95) returns_winsorized = returns.winsorize(min_percentile=0.05, max_percentile=0.95) eps_wisorized = eps.winsorize(min_percentile=0.05, max_percentile=0.95) ty_winsorized = ty.winsorize(min_percentile=0.05, max_percentile=0.95) combined_factor = ( value_winsorized.zscore() + quality_winsorized.zscore() + sentiment_score_winsorized.zscore() + returns_winsorized.zscore() + eps_wisorized.zscore() + ty_winsorized.zscore() ) 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(): returns = (-1) * Returns(window_length = 21) value = Fundamentals.ebit.latest / Fundamentals.enterprise_value.latest quality = Fundamentals.roe.latest sentiment_score = SimpleMovingAverage( inputs=[stocktwits.total_scanned_messages], window_length=21, ) ty = Fundamentals.total_yield.latest #-7.77 wps = Fundamentals.working_capital_per_share.latest #-7.53 epst = Fundamentals.tangible_book_value_per_share.latest gro = Fundamentals.growth_score.latest dollar_volume = AverageDollarVolume(window_length=63) universe = QTradableStocksUS() & (dollar_volume > 10**7) value_winsorized = value.winsorize(min_percentile=0.15, max_percentile=0.85) sentiment_score_winsorized = sentiment_score.winsorize(min_percentile=0.15, max_percentile=0.85) eps_wisorized = wps.winsorize(min_percentile=0.15, max_percentile=0.85) ty_winsorized = ty.winsorize(min_percentile=0.15, max_percentile=0.85) gro_winsorize = gro.winsorize(min_percentile=0.15, max_percentile=0.85) returns_winsorize = returns.winsorize(min_percentile=0.05, max_percentile=0.85) # Here we combine our winsorized factors, z-scoring them to equalize their influence combined_factor = ( value_winsorized.zscore() *0.15 + gro_winsorize.zscore() *0.25 + sentiment_score_winsorized.zscore()* 0.2 + eps_wisorized.zscore() *0.15 + ty_winsorized.zscore() *0.15 + returns_winsorize.zscore() *0.1 ) 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(): value = Fundamentals.ebit.latest / Fundamentals.enterprise_value.latest sentiment_score = SimpleMovingAverage( inputs=[stocktwits.total_scanned_messages], window_length=21, ) ty = Fundamentals.total_yield.latest wps = Fundamentals.working_capital_per_share.latest gro = Fundamentals.growth_score.latest dollar_volume = AverageDollarVolume(window_length=63) universe = QTradableStocksUS() dollar_winsorize = dollar_volume.winsorize(min_percentile=0.2, max_percentile=0.8) value_winsorized = value.winsorize(min_percentile=0.05, max_percentile=0.95) sentiment_score_winsorized = sentiment_score.winsorize(min_percentile=0.05, max_percentile=0.95) eps_wisorized = wps.winsorize(min_percentile=0.05, max_percentile=0.95) ty_winsorized = ty.winsorize(min_percentile=0.05, max_percentile=0.95) gro_winsorize = gro.winsorize(min_percentile=0.05, max_percentile=0.95) combined_factor = ( value_winsorized.zscore() *0.15 + gro_winsorize.zscore() *0.25 + sentiment_score_winsorized.zscore()* 0.15 + eps_wisorized.zscore() *0.15 + ty_winsorized.zscore() *0.15 + dollar_winsorize.zscore() *0.15 ) 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(): value = Fundamentals.ebit.latest / Fundamentals.enterprise_value.latest quality = Fundamentals.roe.latest sentiment_score = SimpleMovingAverage( inputs=[stocktwits.bull_minus_bear], window_length=3, ) workingCapital = Fundamentals.working_capital_per_share.latest sGrowRate = Fundamentals.sustainable_growth_rate.latest dividendYield = Fundamentals.forward_dividend_yield.latest 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_score_winsorized = sentiment_score.winsorize(min_percentile=0.05, max_percentile=0.95) workingCapital_winsorized = workingCapital.winsorize(min_percentile=0.05, max_percentile=0.95) sGrowRate_winsorized = sGrowRate.winsorize(min_percentile=0.05, max_percentile=0.95) dividendYield_winsorized = dividendYield.winsorize(min_percentile=0.05, max_percentile=0.95) combined_factor = (value_winsorized.zscore() + quality_winsorized.zscore() + sentiment_score_winsorized.zscore() + workingCapital_winsorized + sGrowRate_winsorized + dividendYield_winsorized) 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(): 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) total_revenue = Fundamentals.total_revenue.latest yesterday_close = EquityPricing.close.latest yesterday_volume = EquityPricing.volume.latest 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) revenue_winsorized = total_revenue.winsorize(min_percentile=0.05, max_percentile=0.95) close_winsorized = yesterday_close.winsorize(min_percentile=0.05, max_percentile=0.95) volume_winsorized = yesterday_volume.winsorize(min_percentile=0.05, max_percentile=0.95) combined_factor = ( value_winsorized.zscore() + quality_winsorized.zscore() + ((positived_sentiment.zscore() + sentiment_winsorized.zscore()) / 2) + revenue_winsorized.zscore() + close_winsorized.zscore() + volume_winsorized.zscore()) 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(): 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. """ sentiment_score = SimpleMovingAverage( inputs=[stocktwits.bull_minus_bear], window_length=7, ) Asset_Growth_7d = Returns(window_length=8); eveb = morningstar.valuation_ratios.ev_to_ebitda.latest cash_return = morningstar.valuation_ratios.cash_return.latest total_yield = morningstar.valuation_ratios.total_yield.latest #universe = Q1500US() 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 sentiment_score_winsorized = sentiment_score.winsorize(min_percentile=0.05, max_percentile=0.95) Asset_Growth_7d_winsorized = Asset_Growth_7d.winsorize(min_percentile=0.05, max_percentile=0.95) eveb_winsorized = eveb.winsorize(min_percentile=0.05, max_percentile=0.95) cash_return_winsorized = cash_return.winsorize(min_percentile=0.05, max_percentile=0.95) total_yield_winsorized = total_yield.winsorize(min_percentile=0.05, max_percentile=0.95) # Here we combine our winsorized factors, z-scoring them to equalize their influence """ combined_factor = -0.3*Asset_Growth_7d_winsorized.zscore() -0.25*sentiment_score_winsorized.zscore() +0.05*eveb_winsorized.zscore() +0.05*cash_return_winsorized.zscore() +0.35*total_yield_winsorized.zscore(); """ combined_factor = -0.3*Asset_Growth_7d_winsorized.zscore() -0.2*sentiment_score_winsorized.zscore() +0.1*eveb_winsorized.zscore() +0.1*cash_return_winsorized.zscore() +0.3*total_yield_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 & sentiment_score.notnull() & Asset_Growth_7d.notnull(), ) 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=3, ) growthh = Fundamentals.growth_score.latest value_score = Fundamentals.value_score.latest profitability_grade = Fundamentals.profitability_grade.latest basic_average_shares = Fundamentals.basic_average_shares_earnings_reports.latest a = Fundamentals.current_ratio.latest b = Fundamentals.accumulated_depreciation.latest c = Fundamentals.ps_ratio.latest d = Fundamentals.style_score.latest e = Fundamentals.total_yield.latest #f = Fundamentals. #g = Fundamentals. 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.0, max_percentile=1) quality_winsorized = quality.winsorize(min_percentile=0.00, max_percentile=1) sentiment_score_winsorized = sentiment_score.winsorize(min_percentile=0.05, max_percentile=0.95) growthh_winsorized = growthh.winsorize(min_percentile=0.05, max_percentile=0.95) value_score_winsorized = value_score.winsorize(min_percentile=0.05, max_percentile=0.95) basic_average_shares_winzorized = basic_average_shares.winsorize( min_percentile=0.05, max_percentile=0.95) a_winso = a.winsorize(min_percentile=0.05, max_percentile=0.95) b_winso = b.winsorize(min_percentile=0.05, max_percentile=0.95) c_winso = c.winsorize(min_percentile=0.05, max_percentile=0.95) d_winso = d.winsorize(min_percentile=0.05, max_percentile=0.95) e_winso = e.winsorize(min_percentile=0.05, max_percentile=0.95) #f_winso = f.winsorize(min_percentile=0.05, max_percentile=0.95) #g_winso = g.winsorize(min_percentile=0.05, max_percentile=0.95) #profitability_grade_winsorized = profitability_grade.winsorize(min_percentile=0.05,max_percentile=0.95) # Here we combine our winsorized factors, z-scoring them to equalize their influence combined_factor = ( #(-0.1*value_winsorized.zscore() )+ #(-1.1*quality_winsorized.zscore() )+ #(1*sentiment_score_winsorized.zscore()) (1.4 * growthh_winsorized.zscore()) + (-1.6 * value_score_winsorized.zscore()) + (0.6 * a_winso.zscore()) + (0.8 * b_winso.zscore()) + (2.3 * c_winso.zscore()) + (0.75 * d_winso.zscore()) + (-1 * e_winso.zscore()) #(f_winso.zscore()) #(-0.1*basic_average_shares_winzorized.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(): universe = QTradableStocksUS() # Variables seleccionadas del dataframe de Fundamentals value = Fundamentals.ebit.latest / Fundamentals.enterprise_value.latest quality = Fundamentals.roe.latest sentiment_score = SimpleMovingAverage( inputs=[stocktwits.bull_minus_bear], window_length=3, ) buildings_and_improvements = Fundamentals.buildings_and_improvements.latest account_payable = Fundamentals.accounts_payable.latest current_assets = Fundamentals.current_assets.latest total_equity = Fundamentals.total_equity.latest accumulated_depreciation = Fundamentals.accumulated_depreciation.latest diluted_eps_growth = Fundamentals.diluted_eps_growth.latest dps_growth = Fundamentals.dps_growth.latest # Variables (SIN ATIPICOS) 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) buildings_and_improvements = buildings_and_improvements.winsorize( min_percentile=0.05, max_percentile=0.95) account_payable = account_payable.winsorize(min_percentile=0.05, max_percentile=0.95) current_assets = current_assets.winsorize(min_percentile=0.05, max_percentile=0.95) total_equity = total_equity.winsorize(min_percentile=0.05, max_percentile=0.95) accumulated_depreciation = accumulated_depreciation.winsorize( min_percentile=0.05, max_percentile=0.95) diluted_eps_growth = diluted_eps_growth.winsorize(min_percentile=0.05, max_percentile=0.95) dps_growth = dps_growth.winsorize(min_percentile=0.05, max_percentile=0.95) # FACTOR COMBINADO combined_factor = ( quality_winsorized.zscore() * 0.2 + value_winsorized.zscore() * 0.4 + dps_growth.zscore() * 0.15 + sentiment_score_winsorized.zscore() * 0.3 + buildings_and_improvements.zscore() * 0.2 + accumulated_depreciation.zscore() * 0.25 + account_payable.zscore() * 0.01 + current_assets.zscore() * 0.01 + total_equity.zscore() * 0.01 + diluted_eps_growth.zscore() * 0.01) 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 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() fe_rec = fe.ConsensusRecommendations # 5 pe_ratio = Fundamentals.forward_pe_ratio.latest # 4 sentiment_score = SimpleMovingAverage( # 3 inputs=[stocktwits.bullish_intensity], window_length=5, ) mean_close_10 = SimpleMovingAverage(inputs=[USEquityPricing.close], window_length=10) mean_close_30 = SimpleMovingAverage(inputs=[USEquityPricing.close], window_length=30) percent_difference = (mean_close_10 - mean_close_30) / mean_close_30 # 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 pe_ratio_winsorized = pe_ratio.winsorize(min_percentile=0.05, max_percentile=0.95) sentiment_score_winsorized = sentiment_score.winsorize(min_percentile=0.05, max_percentile=0.95) percent_difference_winsorized = percent_difference.winsorize( # 2 min_percentile=0.1, max_percentile=0.9) recent_returns = Returns(window_length=5) # 6 fq1_eps_cons = PeriodicConsensus.slice('EPS', 'qf', 1) # 1 fq2_eps_cons = PeriodicConsensus.slice('EPS', 'qf', 2) fq1_eps_mean = fq1_eps_cons.mean.latest fq2_eps_mean = fq2_eps_cons.mean.latest estimated_growth_factor = (fq2_eps_mean - fq1_eps_mean) / fq1_eps_mean estimated_growth_factor_windsorized = estimated_growth_factor.winsorize( min_percentile=0.01, max_percentile=0.99) # Here we combine our winsorized factors, z-scoring them to equalize their influence combined_factor = (0.01 * fe_rec.total.latest + pe_ratio_winsorized.zscore() + sentiment_score_winsorized.zscore() + 0.005 * percent_difference_winsorized.zscore() + 0.01 * recent_returns.zscore() + estimated_growth_factor_windsorized.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(): qtu = QTradableStocksUS() # Aggregated Insider Transactions insider_txns_form3_90d = Form3AggregatedTrades.slice(False, 90) insider_txns_form4and5_90d = Form4and5AggregatedTrades.slice(False, 90) unique_filers_form3_90d = insider_txns_form3_90d.num_unique_filers.latest unique_buyers_form4and5_90d = insider_txns_form4and5_90d.num_unique_buyers.latest unique_sellers_form4and5_90d = insider_txns_form4and5_90d.num_unique_sellers.latest unique_buyers_90d = unique_filers_form3_90d + unique_buyers_form4and5_90d unique_sellers_90d = unique_sellers_form4and5_90d frac_insiders_buying_90d = unique_buyers_90d / (unique_buyers_90d + unique_sellers_90d) frac_insiders_selling_90d = unique_sellers_90d / (unique_buyers_90d + unique_sellers_90d) alpha_factor = frac_insiders_buying_90d - frac_insiders_selling_90d screen = qtu & ~alpha_factor.isnull() & alpha_factor.isfinite() alpha_winsorized = alpha_factor.winsorize(min_percentile=0.05, max_percentile=0.95, mask=screen) alpha_rank = alpha_winsorized.zscore() # FactSet Estimates – Consensus fq1_eps_cons = PeriodicConsensus.slice('EPS', 'qf', 1) fq2_eps_cons = PeriodicConsensus.slice('EPS', 'qf', 2) fq1_eps_mean = fq1_eps_cons.mean.latest fq2_eps_mean = fq2_eps_cons.mean.latest estimated_growth_factor = (fq2_eps_mean - fq1_eps_mean) / fq1_eps_mean estimated_growth_factor_rank = estimated_growth_factor.winsorize( min_percentile=0.05, max_percentile=0.95).zscore() # Sentdex News Sentiment mean_sentiment_5day = SimpleMovingAverage( inputs=[sentiment.sentiment_signal], window_length=5) # 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, ) # 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) # 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() + alpha_rank + estimated_growth_factor_rank + mean_sentiment_5day) # 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=screen) shorts = combined_factor.bottom(TOTAL_POSITIONS // 2, mask=screen) # 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(): # 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 amortization = Fundamentals.amortization_of_securities.latest dividends = Fundamentals.cash_dividends_paid.latest asst_turnover = Fundamentals.assets_turnover.latest dps_growth = Fundamentals.dps_growth.latest sustainable = Fundamentals.sustainable_growth_rate.latest enterprise_value = Fundamentals.enterprise_value.latest gross_margin = Fundamentals.gross_margin.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) amortization_winsorized = amortization.winsorize(min_percentile=0.05, max_percentile=0.95) dividends_winsorized = dividends.winsorize(min_percentile=0.05, max_percentile=0.95) asst_turnover_winsorized = asst_turnover.winsorize(min_percentile=0.05, max_percentile=0.95) dps_growth_winsorized = dps_growth.winsorize(min_percentile=0.05, max_percentile=0.95) sustainable_winsorized = sustainable.winsorize(min_percentile=0.05, max_percentile=0.95) enterprise_value_winsorized = enterprise_value.winsorize( min_percentile=0.05, max_percentile=0.95) gross_margin_winsorized = gross_margin.winsorize(min_percentile=0.05, max_percentile=0.95) combined_factor = ((0.1 * value_winsorized + 0.1 * quality_winsorized + 0.2 * sentiment_score_winsorized + 0.2 * growth_score_winsorized + 0.3 * gross_margin_winsorized + 0.1 * amortization_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. """ positive_sentiment_pct = (twitter_sentiment.bull_scored_messages.latest / twitter_sentiment.total_scanned_messages.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() yesterday_close = EquityPricing.close.latest yesterday_volume = EquityPricing.volume.latest v1 = Fundamentals.accounts_receivable.latest v2 = Fundamentals.size_score.latest v3 = Fundamentals.style_score.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 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) 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) yesterday_close_winsorized = yesterday_close.winsorize(min_percentile=0.05, max_percentile=0.95) yesterday_volume_winsorized = yesterday_volume.winsorize( min_percentile=0.05, max_percentile=0.95) # Here we combine our winsorized factors, z-scoring them to equalize their influence combined_factor = (positive_sentiment_pct_winsorized.zscore() * 0.8 + value_winsorized.zscore() * 0.5 + quality_winsorized.zscore() * 0.5 + sentiment_score_winsorized.zscore() * 0.5 + v1_winsorized.zscore() * 0.5 + v2_winsorized.zscore() * 0.5 + v3_winsorized.zscore() * 0.5 + yesterday_close_winsorized.zscore() * 0.5 + yesterday_volume_winsorized.zscore() * 0.7) # 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, 'close': yesterday_close, 'volume': yesterday_volume }, screen=long_short_screen, domain=US_EQUITIES) 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 enterprise = SimpleMovingAverage( inputs=[Fundamentals.enterprise_value], window_length=10, ) marketcap = SimpleMovingAverage( inputs=[Fundamentals.market_cap], window_length=10, ) earnings = SimpleMovingAverage(inputs=[Fundamentals.ebit], window_length=10) equitymedia = (EquityPricing.high.latest + EquityPricing.low.latest) / 2 high = SimpleMovingAverage(inputs=[EquityPricing.high], window_length=10) low = SimpleMovingAverage(inputs=[EquityPricing.low], window_length=10) 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 enterprise_winsorized = enterprise.winsorize(min_percentile=0.05, max_percentile=0.95) marketcap_winsorized = marketcap.winsorize(min_percentile=0.05, max_percentile=0.95) earnings_winsorized = earnings.winsorize(min_percentile=0.05, max_percentile=0.95) equitymedia_winsorized = equitymedia.winsorize(min_percentile=0.05, max_percentile=0.95) high_winsorized = high.winsorize(min_percentile=0.05, max_percentile=0.95) low_winsorized = low.winsorize(min_percentile=0.05, max_percentile=0.95) # Here we combine our winsorized factors, z-scoring them to equalize their influence combined_factor = (enterprise_winsorized.zscore() + marketcap_winsorized.zscore() + earnings_winsorized.zscore() + high_winsorized.zscore() + low_winsorized.zscore() + equitymedia_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(): universe = QTradableStocksUS() # Variables seleccionadas del dataframe de Fundamentals value = Fundamentals.ebit.latest / Fundamentals.enterprise_value.latest sentiment_score = SimpleMovingAverage( inputs=[stocktwits.bull_minus_bear], window_length=3, ) quality = Fundamentals.roe.latest working_capital = Fundamentals.working_capital.latest restricted_cash = Fundamentals.restricted_cash.latest accumulated_depreciation = Fundamentals.accumulated_depreciation.latest dps_growth = Fundamentals.dps_growth.latest capital_stock = Fundamentals.capital_stock.latest mcap = Fundamentals.market_cap.latest daily_returns = Returns(window_length=2) # Variables (SIN ATIPICOS) value_winsorized = value.winsorize(min_percentile=0.05, max_percentile=0.95) sentiment_score_winsorized = sentiment_score.winsorize(min_percentile=0.05, max_percentile=0.95) quality_winsorized = quality.winsorize(min_percentile=0.05, max_percentile=0.95) working_capital = working_capital.winsorize(min_percentile=0.05, max_percentile=0.95) restricted_cash = restricted_cash.winsorize(min_percentile=0.05, max_percentile=0.95) accumulated_depreciation = accumulated_depreciation.winsorize( min_percentile=0.05, max_percentile=0.95) dps_growth = dps_growth.winsorize(min_percentile=0.05, max_percentile=0.95) capital_stock = capital_stock.winsorize(min_percentile=0.05, max_percentile=0.95) mcap = mcap.winsorize(min_percentile=0.05, max_percentile=0.95) daily_returns = daily_returns.winsorize(min_percentile=0.05, max_percentile=0.95) # FACTOR COMBINADO combined_factor = ( quality_winsorized.zscore() * 0.01 + accumulated_depreciation.zscore() * 0.03 + working_capital.zscore() * 0.05 + dps_growth.zscore() * 0.85 + value_winsorized.zscore() * 0.01 + mcap.zscore() * 0.01 + capital_stock.zscore() * 0.01 + sentiment_score_winsorized.zscore() * 0.01 + restricted_cash.zscore() * 0.01 + daily_returns.zscore( groupby=mstar.company_reference.country_id.latest) * 0.01) 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(): # 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(): """ パイプラインを作成して返す関数 パイプラインの構築は、NotebookとAlgorithmの両方で動作させることができるので、Notebook で検証したアルファをコピペしてアルゴリズムで使うことが可能。 【Execise】make_pipeline をNotebookにコピーして動作することを確認しよう。 Returns ------- pipe : Pipeline Represents computation we would like to perform on the assets that make it through the pipeline screen. """ # ファクターその1:バリューファクター(この時点では生データ) value = Fundamentals.ebit.latest / Fundamentals.enterprise_value.latest # ファクターその2:クオリティファクター(ROE)(この時点では生データ) quality = Fundamentals.roe.latest # ファクターその3:センチメントファクター(この時点では生データ) sentiment_score = SimpleMovingAverage( inputs=[stocktwits.bull_minus_bear], window_length=3, ) # ユニバースはQTradableStockUS()を使う universe = QTradableStocksUS() # 生データからwinsorizeによってスコア化 # バリューファクタースコア 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) # 3つのファクターを合成して、1つのアルファを構成 # 【Execise】ファクターの合成方法を変えてバックテストしてみよう! combined_factor = (value_winsorized.zscore() + quality_winsorized.zscore() + sentiment_score_winsorized.zscore()) # QTradableStocks構成銘柄の中から、さらに、combined_fatctorが上位のものだけを取得 longs = combined_factor.top(TOTAL_POSITIONS // 2, mask=universe) # QTradableStocks構成銘柄の中から、さらに、combined_fatctorが下位のものだけを取得 shorts = combined_factor.bottom(TOTAL_POSITIONS // 2, mask=universe) # longとshortsの構成銘柄を組み合わせることで、最終的なフィルタを構築 long_short_screen = (longs | shorts) # パイプラインを作成 pipe = Pipeline( columns={ 'longs': longs, 'shorts': shorts, 'combined_factor': combined_factor }, # フィルタリング(longs または shorts に含まれる銘柄でフィルタリング) 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. """ #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. """ # Ganancias menos gastos sobre el valor total de la empresa incluida la deuda value = Fundamentals.ebit.latest / Fundamentals.enterprise_value.latest # Utilidad quality = Fundamentals.roe.latest # Ingresos netos sobre activos totales promedio de los ultimos 5 años interest = Fundamentals.roa5_yr_avg.latest # Los gastos operativos son costos recurrentes primarios asociados con las operaciones centrales (que no sean el costo de los bienes vendidos) en los que se incurre para generar ventas. oExpense = Fundamentals.operating_expense.latest # Costo total del personal que se paga a los empleados que no forma parte de los gastos de venta, generales y administrativos. cost = Fundamentals.staff_costs.latest sentiment_score = SimpleMovingAverage( inputs=[stocktwits.bull_minus_bear], window_length=3, ) universe = QTradableStocksUS() # Transformacion de las estadisticas al limitar los valores extremos value_winsorized = value.winsorize(min_percentile=0.05, max_percentile=0.95) quality_winsorized = quality.winsorize(min_percentile=0.05, max_percentile=0.95) interest_winsorized = interest.winsorize(min_percentile=0.05, max_percentile=0.95) oExpense_winsorized = oExpense.winsorize(min_percentile=0.1, max_percentile=0.9) cost_winsorized = cost.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 = ( value_winsorized.zscore() + quality_winsorized.zscore() + oExpense_winsorized.zscore() + #interest_winsorized.zscore() + #cost_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={ 'longs': longs, 'shorts': shorts, 'combined_factor': combined_factor }, screen=long_short_screen) return pipe