def make_pipeline(): """ Create and return 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. """ # Basic momentum metrics. cross_momentum = CrossSectionalMomentum() abs_momentum = Returns(inputs=[USEquityPricing.close], window_length=252) # We only want to trade relatively liquid stocks. # Build a filter that only passes stocks that have $10,000,000 average # daily dollar volume over the last 20 days. dollar_volume = AverageDollarVolume(window_length=20) is_liquid = (dollar_volume > 1e7) # We also don't want to trade penny stocks, which we define as any stock with an # average price of less than $5.00 over the last 200 days. sma_200 = SimpleMovingAverage(inputs=[USEquityPricing.close], window_length=200) not_a_penny_stock = (sma_200 > 5) # Before we do any other ranking, we want to throw away the bad assets. initial_screen = (is_liquid & not_a_penny_stock) # By applying a mask to the rank computations, we remove any stocks that failed # to meet our initial criteria **before** computing ranks. This means that the # stock with rank 10.0 is the 10th-lowest stock that passed `initial_screen`. combined_rank = (cross_momentum.rank(mask=initial_screen) + abs_momentum.rank(mask=initial_screen)) # Build Filters representing the top and bottom 5% of stocks by our combined ranking system. # We'll use these as our tradeable universe each day. longs = combined_rank.percentile_between(95, 100) shorts = combined_rank.percentile_between(0, 5) # The final output of our pipeline should only include # the top/bottom 5% of stocks by our criteria. pipe_screen = (longs | shorts) pipe_columns = { 'longs': longs, 'shorts': shorts, 'combined_rank': combined_rank, 'abs_momentum': abs_momentum, 'cross_momentum': cross_momentum } # Create pipe pipe = Pipeline(columns=pipe_columns, screen=pipe_screen) return pipe
def initialize(context): # UNIVERSE DECLARATION universe = QTradableStocksUS() # ATTACH PIPELINE NAME pipe = Pipeline(screen=universe) attach_pipeline(pipe, 'my pipe') # ADD SECTOR TO THE PIPELINE sector = Fundamentals.morningstar_sector_code.latest pipe.add(sector, 'sector') # ADD MONTHLY RETURN FACTOR AND RANKED RETURN FACTOR monthly_return = Returns(window_length=21) monthly_rank = monthly_return.rank(mask=universe) pipe.add(monthly_return, 'Mreturn') pipe.add(monthly_rank, 'Mrank') # ADD CUMULATIVE MONTHLY RETURNS TO THE PIPELINE prod_return = np.prod(monthly_return) pipe.add(prod_return, 'prodReturn') # DEFINE OUR PRE-FILTERED LONG AND SHORT LISTS longs = (prod_return > 0) pipe.add(longs, 'longs') # SETTINGS #---------- # SCHEDULE SETTINGS FOR THE 'REBALANCE' FUNCTION schedule_function(func=rebalance, date_rule=date_rules.month_start(), time_rule=time_rules.market_open(), half_days=True) # SCHEDULE SETTINGS FOR THE 'RECORD VARS' FUNCTION schedule_function(func=record_vars, date_rule=date_rules.month_start(), time_rule=time_rules.market_open(), half_days=True) # LEVERAGE SETTINGS (CAN BE ADJUSTED) context.long_leverage = 0.5 context.short_leverage = -0.5 # SLIPPAGE SETTINGS (CAN BE ADJUSTED - DEFAULT) set_slippage(us_equities=slippage.FixedBasisPointsSlippage( basis_points=5, volume_limit=0.1)) # COMMISSION SETTINGS (CAN BE ADJUSTED - SET TO INTERACTIVE BROKERS COMMISSION PRICING) set_commission( us_equities=commission.PerShare(cost=0.005, min_trade_cost=1))
def make_pipeline(context): """ A function to create our pipeline (dynamic security selector). The pipeline is used to rank securities based on different factors, including builtin facotrs, or custom factors that you can define. Documentation on pipeline can be found here: https://www.quantopian.com/help#pipeline-title """ # Create a pipeline object. pipe = Pipeline() # Create a dollar_volume factor using default inputs and window_length. # This is a builtin factor. dollar_volume = AverageDollarVolume(window_length=1) pipe.add(dollar_volume, 'dollar_volume') # Create a recent_returns factor with a 5-day returns lookback. This is # a custom factor defined below (see RecentReturns class). recent_returns = Returns(window_length=context.returns_lookback) pipe.add(recent_returns, 'recent_returns') # Define high dollar-volume filter to be the top 5% of securities by dollar volume. high_dollar_volume = dollar_volume.percentile_between(95, 100) # 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, mask=high_dollar_volume) high_returns = recent_returns.percentile_between(90, 100, mask=high_dollar_volume) # Factors return a scalar value for each security in the entire universe # of securities. Here, we add the recent_returns rank factor to our pipeline # and we provide it with a mask such that securities that do not pass the mask # (i.e. do not have high dollar-volume), are not considered in the ranking. pipe.add(recent_returns.rank(mask=high_dollar_volume), 'recent_returns_rank') # Add a filter to the pipeline such that only high-return and low-return # securities are kept. pipe.set_screen(low_returns | high_returns) # Add the low_returns and high_returns filters as columns to the pipeline so # that when we refer to securities remaining in our pipeline later, we know # which ones belong to which category. pipe.add(low_returns, 'low_returns') pipe.add(high_returns, 'high_returns') return pipe
def make_pipeline(): # get factors mktcap = Fundamentals.market_cap.latest price_close = USEquityPricing.close.latest # get factors, higher is better roe = Fundamentals.roe.latest fcf_yield = Fundamentals.fcf_yield.latest ret_20 = Returns(window_length=20) # compare built-in valuation ratio with manually calculated price_close = USEquityPricing.close.latest fcf_per_share = Fundamentals.fcf_per_share.latest fcf_yield_manual = fcf_per_share / price_close # get ranks, masked by the universe, higher is better quality = roe.rank(method='average', mask=min_liq_univ()) value = fcf_yield.rank(method='average', mask=min_liq_univ()) momentum = ret_20.rank(method='average', mask=min_liq_univ()) # combine ranks qvm = (quality + value + momentum).rank(method='average', mask=min_liq_univ()) # Sort into 10 deciles num_quantiles = 10 qvm_quantiles = qvm.quantiles(num_quantiles, mask=min_liq_univ()) long_decile = qvm_quantiles.eq(num_quantiles - 1) short_decile = qvm_quantiles.eq(0) # Get top 10 and bottom 10 stocks by rank long_10 = qvm.top(10, mask=min_liq_univ()) short_10 = qvm.bottom(10, mask=min_liq_univ()) return Pipeline(columns={ 'mktcap': mktcap, 'fcf_yield': fcf_yield, 'fcf_yield_manual': fcf_yield_manual, 'roe': roe, 'ret_20': ret_20, 'quality': quality, 'value': value, 'momentum': momentum, 'qvm': qvm, 'long_10': long_10 }, screen=min_liq_univ())
def make_pipeline(context): """ A function to create our pipeline (dynamic security selector). The pipeline is used to rank securities based on different factors, including builtin facotrs, or custom factors that you can define. Documentation on pipeline can be found here: https://www.quantopian.com/help#pipeline-title """ # Create a pipeline object. pipe = Pipeline() # Create a dollar_volume factor using default inputs and window_length. # This is a builtin factor. dollar_volume = AverageDollarVolume(window_length=1) pipe.add(dollar_volume, 'dollar_volume') # Create a recent_returns factor with a 5-day returns lookback. This is # a custom factor defined below (see RecentReturns class). recent_returns = Returns(window_length=context.returns_lookback) pipe.add(recent_returns, 'recent_returns') # Define high dollar-volume filter to be the top 5% of securities by dollar volume. high_dollar_volume = dollar_volume.percentile_between(95, 100) # 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,mask=high_dollar_volume) high_returns = recent_returns.percentile_between(90,100,mask=high_dollar_volume) # Factors return a scalar value for each security in the entire universe # of securities. Here, we add the recent_returns rank factor to our pipeline # and we provide it with a mask such that securities that do not pass the mask # (i.e. do not have high dollar-volume), are not considered in the ranking. pipe.add(recent_returns.rank(mask=high_dollar_volume), 'recent_returns_rank') # Add a filter to the pipeline such that only high-return and low-return # securities are kept. pipe.set_screen(low_returns | high_returns) # Add the low_returns and high_returns filters as columns to the pipeline so # that when we refer to securities remaining in our pipeline later, we know # which ones belong to which category. pipe.add(low_returns, 'low_returns') pipe.add(high_returns, 'high_returns') return pipe
def make_pipeline(): """ pipeline を作る make_pipeline を作ったほうが,research にもコピペして使えるし,テストや修正も簡単に出来るので,幸せになれます """ # クロスモメンタム cross_momentum = CrossSectionalMomentum() # Returns で過去252分全てのクローズベースのリターンを取得 abs_momentum = Returns(input=[USEquityPricing.close], window_length = 252) # 流動性がある株式だけ取引する.過去20日間,平均1千万ドル平均の取引高(price*volume)があるものだけを取引 dollar_volume = AverageDollarVolume(window_length=20) is_liquid = (dollar_volume > le7) # 過去200日平均で株価5ドル以下のペニーストックはトレードしない. sma_200 = SimpleMovingAverage(inputs = [USEquityPricing.close], window_length=200) not_a_penny_stock = (sma_200 > 5) # 不必要な銘柄は取り除く initial_screen = (is_liquid & not_a_penny_stock) # cross momentum を適用したあとに,ランク付けをする combined_rank = (cross_momentum.rank(mask=initial_screen) + abs_momentum.rank(mask=initial_screen)) # top 5 % をロング longs = combined_rank.percentile_between(95, 100) shorts = combined_rank.percentile_between(0, 5) # パイプラインにロングショートする銘柄を取得 pipe_screen = (longs | shorts) pipe_columns = { 'longs': longs, 'shorts': shorts, 'combined_rank': combined_rank, 'abs_momentum': abs_momentum, 'cross_momentum': cross_momentum, } # パイプ作成 pipe = Pipeline(columns=pipe_columns, screen=pipe_screen) return pipe
def make_pipeline(context): #create pipeline pipe = Pipeline() #use built in factor AverageDollarVolume to screen for liquid stocks avg_dollar_volume = AverageDollarVolume(window_length=1) pipe.add(avg_dollar_volume, 'avg_dollar_volume') #use built in factor Returns to get returns over the recent_lookback window recent_returns = Returns(window_length=context.returns_lookback) pipe.add(recent_returns, 'recent_returns') #filter out stocks in the top % of dollar volume high_dollar_volume = avg_dollar_volume.percentile_between(95, 100) #rank the recent returns in the high dollar volume group and add to pipe pipe.add(recent_returns.rank(mask=high_dollar_volume), 'recent_returns_rank') #get stocks with the highest and lowest returns in the high dollar volume group low_returns = recent_returns.percentile_between(0, 10, mask=high_dollar_volume) high_returns = recent_returns.percentile_between(90, 100, mask=high_dollar_volume) #add high and low returns as columns to pipeline for easier data mgmt pipe.add(high_returns, 'high_returns') pipe.add(low_returns, 'low_returns') ######Earnings Announcement Risk Framework############# # https://www.quantopian.com/data/eventvestor/earnings_calendar # EarningsCalendar.X is the actual date of the announcement # E.g. 9/12/2015 pipe.add(EarningsCalendar.next_announcement.latest, 'next') pipe.add(EarningsCalendar.previous_announcement.latest, 'prev') # BusinessDaysX is the integer days until or after the closest # announcement. So if AAPL had an earnings announcement yesterday, # prev_earnings would be 1. If it's the day of, it will be 0. # For BusinessDaysUntilNextEarnings(), it is common that the value # is NaaN because we typically don't know the precise date of an # earnings announcement until about 15 days before ne = BusinessDaysUntilNextEarnings() pe = BusinessDaysSincePreviousEarnings() pipe.add(ne, 'next_earnings') pipe.add(pe, 'prev_earnings') # The number of days before/after an announcement that you want to # avoid an earnings for. # pipe.set_screen ( (ne.isnan() | (ne > 3)) & (pe > 3) ) #####Set Pipe based on the desired framework###### #screen the pipeline by the high and low returns(and high dollar volume, implicitly pipe.set_screen(high_returns | low_returns | ((ne.isnan() | (ne > 3)) & (pe > 3))) # pipe.set_screen(high_returns | low_returns) return pipe