def compute_factors(): """Create factor pipeline incl. mean reversion, filtered by 30d Dollar Volume; capture factor ranks""" mean_reversion = MeanReversion() dollar_volume = AverageDollarVolume(window_length=30) return Pipeline(columns={'longs' : mean_reversion.bottom(N_LONGS), 'shorts' : mean_reversion.top(N_SHORTS), 'ranking': mean_reversion.rank(ascending=False)}, screen=dollar_volume.top(VOL_SCREEN))
def create_high_dollar_volume_pipeline(): pipe = Pipeline() dollar_volume = AverageDollarVolume( window_length=63) # 63 days = 1 quarter pipe.add(dollar_volume, 'dollar_volume') high_dollar_volume = dollar_volume.percentile_between( 95, 100) # top 5% by dollar volume pipe.set_screen(high_dollar_volume) return pipe
def make_pipeline(asset_finder): private_universe = private_universe_mask( hs300.tolist(),asset_finder=asset_finder) #print private_universe_mask(['000001','000002','000005'],asset_finder=asset_finder) ###################################################################################################### returns = Returns(inputs=[USEquityPricing.close], window_length=5) # 预测一周数据 ###################################################################################################### ep = 1/Fundamental(mask = private_universe,asset_finder=asset_finder).pe bp = 1/Fundamental(mask = private_universe,asset_finder=asset_finder).pb bvps = Fundamental(mask = private_universe,asset_finder=asset_finder).bvps market = Fundamental(mask = private_universe,asset_finder=asset_finder).outstanding rev20 = Returns(inputs=[USEquityPricing.close], window_length=20,mask = private_universe) vol20 = AverageDollarVolume(window_length=20,mask = private_universe) illiq = ILLIQ(window_length=22,mask = private_universe) rsi = RSI(window_length=22,mask = private_universe) mom = Momentum(window_length=252,mask = private_universe) sector = get_sector(asset_finder=asset_finder,mask=private_universe) ONEHOTCLASS,sector_indict_keys = get_sector_by_onehot(asset_finder=asset_finder,mask=private_universe) pipe_columns = { 'ep':ep.zscore(groupby=sector).downsample('month_start'), 'bp':bp.zscore(groupby=sector).downsample('month_start'), 'bvps':bvps.zscore(groupby=sector).downsample('month_start'), 'market_cap': market.zscore(groupby=sector).downsample('month_start'), 'vol20':vol20.zscore(groupby=sector), 'rev20':rev20.zscore(groupby=sector), 'ILLIQ':illiq.zscore(groupby=sector,mask=illiq.percentile_between(1, 99)), 'mom' :mom.zscore(groupby=sector,mask=mom.percentile_between(1, 99)), 'rsi' :rsi.zscore(groupby=sector,mask=rsi.percentile_between(1, 99)), #'sector':sector, #'returns':returns.quantiles(100), 'returns': returns.zscore(), } # pipe_screen = (low_returns | high_returns) pipe = Pipeline(columns=pipe_columns, screen=private_universe, ) i = 0 for c in ONEHOTCLASS: pipe.add(c,sector_indict_keys[i]) i +=1 return pipe
def make_pipeline(): dollar_volume = AverageDollarVolume(window_length=1) high_dollar_volume = dollar_volume.percentile_between(N, 100) recent_returns = Returns(window_length=N, mask=high_dollar_volume) low_returns = recent_returns.percentile_between(0, 10) high_returns = recent_returns.percentile_between(N, 100) pipe_columns = { 'low_returns': low_returns, 'high_returns': high_returns, 'recent_returns': recent_returns, 'dollar_volume': dollar_volume } pipe_screen = (low_returns | high_returns) pipe = Pipeline(columns=pipe_columns, screen=pipe_screen) return pipe
def make_pipeline(): """Sets up the pipeline""" dollar_volume = AverageDollarVolume(window_length=20) adv1000 = dollar_volume.top(1000) fd = Fundamentals(mask=adv1000) market_cap = fd.cshoq * fd.prccq # this is how to calculate market cap with Computstat fields book_equity = fd.seqq - fd.PS # this is a quick way to calculate book_equity book_to_price = book_equity / market_cap biggest = market_cap.top(500, mask=adv1000) smallest = market_cap.bottom(500, mask=adv1000) highpb = book_to_price.top(500, mask=adv1000) lowpb = book_to_price.bottom(500, mask=adv1000) momentum = Momentum(mask=adv1000) # momentum high_momentum = momentum.top(500, mask=adv1000) low_momentum = momentum.bottom(500, mask=adv1000) volatility = Volatility(mask=adv1000) highvol = volatility.top(500, mask=adv1000) lowvol = volatility.bottom(500, mask=adv1000) streversal = RSI(window_length=14, mask=adv1000) high_streversal = streversal.top(500, mask=adv1000) low_streversal = streversal.bottom(500, mask=adv1000) universe = biggest | smallest | highpb | lowpb | low_momentum | high_momentum return Pipeline( columns={ 'returns': Returns(window_length=2), # 'market_cap': market_cap, # not needed # 'book_to_price': book_to_price, # not needed 'biggest': biggest, 'smallest': smallest, 'highpb': highpb, 'lowpb': lowpb, # 'momentum': momentum, # not needed 'low_momentum': low_momentum, 'high_momentum': high_momentum, # 'volatility': volatility, # not needed 'highvol': highvol, 'lowvol': lowvol, # 'streversal': streversal, # not needed 'high_streversal': high_streversal, 'low_streversal': low_streversal }, screen=universe)
def test_dollar_volume(self): results = self.engine.run_pipeline( Pipeline( columns={ 'dv1': AverageDollarVolume(window_length=1), 'dv5': AverageDollarVolume(window_length=5), }), self.dates[5], self.dates[-1], ) expected_1 = (self.raw_data[5:]**2) * 2 assert_frame_equal(results['dv1'].unstack(), expected_1) expected_5 = rolling_mean((self.raw_data**2) * 2, window=5)[5:] assert_frame_equal(results['dv5'].unstack(), expected_5)
def make_pipeline(): # Base universe set to the Q500US universe = universe_filters() # Q3000US() # Create the factors we want use #rsi = RSI() price_close = USEP.close.latest fd=Fundamentals() price_volm = USEP.volume.latest mc = fd.marketcap de = fd.de dnc = fd.debtnc eusd = fd.equityusd fcf = fd.fcf # Create a filter to select our 'universe' # Our universe is made up of stocks that have a non-null sentiment signal that was updated in # the last day, are not within 2 days of an earnings announcement, are not announced acquisition # targets, and are in the Q1500US. ltd_to_eq_rank = np.divide(dnc.latest, eusd.latest) #Fundamentals.long_term_debt_equity_ratio.latest # Create a screen for our Pipeline #adv5000 = AverageDollarVolume(window_length = 44).percentile_between(90,100) #mcap3000 = mc.latest.percentile_between(90,100) #universe = universe & adv5000 & mcap3000 adv5000 = AverageDollarVolume(window_length = 30).top(1500) mcap3000 = mc.latest.top(500) universe = universe & adv5000 & mcap3000 universe = universe & (fcf.latest > 1.5e8) & (mc.latest >25e6) & (price_close > 10.0) & (price_volm > 1500000) & (ltd_to_eq_rank < 32.0) #100000 is too big #10000 is too small. Cannot get subscription for ILTB de_f = de.latest #Fundamentals.long_term_debt_equity_ratio.latest #print(dir(universe)) #universe=~universe.matches('.*[-]*$') indebted = ltd_to_eq_rank.top(NUM_TOP_INDEBTED, mask=universe) #10 30 150 60 dnc_f = dnc.latest eusd_f = eusd.latest fcf_f = fcf.latest #mom = Returns(inputs=[USEP.open],window_length=126,mask=indebted) #mom_av = SimpleMovingAverage(inputs=[mom],window_length=22,mask=indebted) pipe = Pipeline(columns={ 'close':price_close, 'volm' :price_volm, 'ltd_to_eq_rank': ltd_to_eq_rank, 'de' : de_f, 'dnc' : dnc_f, 'eusd': eusd_f, 'fcf': fcf_f, 'adv': adv5000, 'mcap': mcap3000, #' mom' : mom, # 'mom_av': mom_av }, screen=indebted) return pipe
def TradableStocksUS(sector): # Equities listed as common stock (not preferred stock, ETF, ADR, LP, etc) common_stock = master.SecuritiesMaster.usstock_SecurityType2.latest.eq( 'Common Stock') # Filter for primary share equities; primary shares can be identified by a # null usstock_PrimaryShareSid field (i.e. no pointer to a primary share) is_primary_share = master.SecuritiesMaster.usstock_PrimaryShareSid.latest.isnull( ) in_sector = master.SecuritiesMaster.usstock_Sector.latest.eq(sector) # combine the security type filters to begin forming our universe tradable_stocks = common_stock & is_primary_share & in_sector # also require high dollar volume tradable_stocks = AverageDollarVolume( window_length=200, mask=tradable_stocks).percentile_between(90, 100) # also require price > $5. Note that we use Latest(...) instead of EquityPricing.close.latest # so that we can pass a mask tradable_stocks = Latest([USEquityPricing.close], mask=tradable_stocks) > 10 # also require no missing data for 200 days tradable_stocks = AllPresent(inputs=[USEquityPricing.close], window_length=200, mask=tradable_stocks) tradable_stocks = All([USEquityPricing.volume.latest > 0], window_length=200, mask=tradable_stocks) return tradable_stocks
def price_pipeline(param_dict): n_days = param_dict["n_days"] n_stocks = param_dict["n_stocks"] min_price = param_dict["min_price"] # only trade stocks with price > min_price price_filter = USEquityPricing.close.latest > min_price # look at stocks with high weekly dollar volume high_dollar_volume = AverageDollarVolume(window_length=5).top(n_stocks) # create universe of stocks universe = (price_filter & high_dollar_volume) # initialize columns columns = {} # add equity pricing data for n_days columns["price_1"] = USEquityPricing.close.latest for i in range(2, n_days + 1): name = "price_" + str(i) val = CloseOnN(window_length=i) columns[name] = val return Pipeline(columns=columns, screen=universe), factor_dict(columns)
def test_mean_reversion_5day_sector_neutral_smoothed(fn): column_name = 'Mean_Reversion_5Day_Sector_Neutral_Smoothed' start_date_str = '2015-01-05' end_date_str = '2015-01-07' # Build engine trading_calendar = get_calendar('NYSE') bundle_data = bundles.load(project_helper.EOD_BUNDLE_NAME) engine = project_helper.build_pipeline_engine(bundle_data, trading_calendar) # Build pipeline universe_window_length = 2 universe_asset_count = 4 universe = AverageDollarVolume( window_length=universe_window_length).top(universe_asset_count) pipeline = Pipeline(screen=universe) run_pipeline_args = { 'pipeline': pipeline, 'start_date': pd.Timestamp(start_date_str, tz='utc'), 'end_date': pd.Timestamp(end_date_str, tz='utc') } fn_inputs = { 'window_length': 3, 'universe': universe, 'sector': project_helper.Sector() } fn_correct_outputs = OrderedDict([ ('pipline_out', pd.DataFrame([ 0.44721360, 1.34164079, -1.34164079, -0.44721360, 1.34164079, 0.44721360, -1.34164079, -0.44721360, 0.44721360, 1.34164079, -1.34164079, -0.44721360 ], engine.run_pipeline(**run_pipeline_args).index, [column_name])) ]) print('Running Integration Test on pipeline:') print('> start_dat = pd.Timestamp(\'{}\', tz=\'utc\')'.format( start_date_str)) print('> end_date = pd.Timestamp(\'{}\', tz=\'utc\')'.format(end_date_str)) print('> universe = AverageDollarVolume(window_length={}).top({})'.format( universe_window_length, universe_asset_count)) print('> factor = {}('.format(fn.__name__)) print(' window_length={},'.format(fn_inputs['window_length'])) print(' universe=universe,') print(' sector=project_helper.Sector())') print('> pipeline.add(factor, \'{}\')'.format(column_name)) print('> engine.run_pipeline(pipeline, start_dat, end_date)') print('') pipeline.add(fn(**fn_inputs), column_name) assert_output(engine.run_pipeline, run_pipeline_args, fn_correct_outputs, check_parameter_changes=False)
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 """ # Create a pipeline object. # Create a dollar_volume factor using default inputs and window_length. # This is a builtin factor. dollar_volume = AverageDollarVolume(window_length=1) # Define high dollar-volume filter to be the top 2% of stocks by dollar # volume. high_dollar_volume = dollar_volume.percentile_between(95, 100) # Create a recent_returns factor with a 5-day returns lookback for all securities # in our high_dollar_volume Filter. This is a custom factor defined below (see # RecentReturns class). recent_returns = Returns( window_length=16, mask=high_dollar_volume) # Define high and low returns filters to be the bottom 1% and top 1% of # securities in the high dollar-volume group. low_returns = recent_returns.percentile_between(0, 5) high_returns = recent_returns.percentile_between(95, 100) # Define a column dictionary that holds all the Factors pipe_columns = { 'low_returns': low_returns, 'high_returns': high_returns, 'recent_returns': recent_returns, 'dollar_volume': dollar_volume } # Add a filter to the pipeline such that only high-return and low-return # securities are kept. # pipe_screen = (low_returns & liquidity_filter | high_returns & vol_filter) pipe_screen = (low_returns | high_returns) # Create a pipeline object with the defined columns and screen. pipe = Pipeline(columns=pipe_columns, screen=pipe_screen) return pipe
def make_pipeline(): """ Create a pipeline to select stocks each day. """ universe = TradableStocksUS('Real Estate') | TradableStocksUS('Utilities') | \ TradableStocksUS('Consumer Staples') | TradableStocksUS('Technology') | \ TradableStocksUS('Financials') | TradableStocksUS('Energy') | \ TradableStocksUS('Materials') | TradableStocksUS('Health Care') | \ TradableStocksUS('Industrials') | TradableStocksUS('Consumer Discretionary') | \ TradableStocksUS('Communications') roic = shfd.slice(dimension='MRT', period_offset=0).ROIC.latest ebit = shfd.slice(dimension='MRQ', period_offset=0).EBIT.latest ev = shfd.slice(dimension='MRQ', period_offset=0).EV.latest volatility = AnnualizedVolatility(window_length=100) value = ebit / ev roic_rank = roic.rank(mask=universe) value_rank = value.rank(mask=universe) volatility_rank = volatility.rank(mask=universe, ascending=False) spy_ma100_price = SMA(inputs=[USEquityPricing.close], window_length=100)[algo.sid("FIBBG000BDTBL9")] spy_price = USEquityPricing.close.latest[algo.sid("FIBBG000BDTBL9")] momentum_score = MomentumScore() overall_rank = roic_rank + value_rank + volatility_rank # seven_month_returns = Returns(window_length=148, mask=universe,) # one_month_returns = Returns(window_length=30, mask=universe,) pipeline = Pipeline( columns={ 'stock': master.SecuritiesMaster.Symbol.latest, 'sid': master.SecuritiesMaster.Sid.latest, 'sector': master.SecuritiesMaster.usstock_Sector.latest, 'average_dollar_volume': AverageDollarVolume(window_length=200), 'price': EquityPricing.close.latest, 'volume': EquityPricing.volume.latest, 'roic': roic, 'value': value, 'volatility': volatility, 'roic_rank': roic_rank, 'value_rank': value_rank, 'momentum': momentum_score, 'momentum_decile': momentum_score.deciles(), 'volatility_decile': volatility.deciles(), 'overall_rank': overall_rank, 'overall_rank_decile': overall_rank.deciles(), 'trend_filter': spy_price > spy_ma100_price, # 'returns' : one_month_returns - seven_month_returns }, screen=universe) return pipeline
def make_pipeline(): """ Create a pipeline that filters by dollar volume and calculates 1-year return. """ pipeline = Pipeline(columns={ "1y_returns": Returns(window_length=252), }, screen=AverageDollarVolume(window_length=30) > 10e6) return pipeline
def make_pipeline(): russell_universe = StaticAssets( symbols( ['AAPL', 'AA', 'KKD', 'MON', 'SPY', 'XOM', 'JNJ', 'HD', 'MSFT'])) filt = AverageDollarVolume(window_length=30, mask=russell_universe) > 10e6 pipeline = Pipeline(columns={ "1y_returns": Returns(window_length=252), }, screen=filt) return pipeline
def test_dollar_volume(self): results = self.engine.run_pipeline( Pipeline( columns={ 'dv1': AverageDollarVolume(window_length=1), 'dv5': AverageDollarVolume(window_length=5), 'dv1_nan': AverageDollarVolume( window_length=1, inputs=[USEquityPricing.open, USEquityPricing.volume], ), 'dv5_nan': AverageDollarVolume( window_length=5, inputs=[USEquityPricing.open, USEquityPricing.volume], ), }), self.dates[5], self.dates[-1], ) expected_1 = (self.raw_data[5:]**2) * 2 assert_frame_equal(results['dv1'].unstack(), expected_1) expected_5 = rolling_mean((self.raw_data**2) * 2, window=5)[5:] assert_frame_equal(results['dv5'].unstack(), expected_5) # The following two use USEquityPricing.open and .volume as inputs. # The former uses self.raw_data_with_nans, and the latter uses # .raw_data * 2. Thus we multiply instead of squaring as above. expected_1_nan = (self.raw_data_with_nans[5:] * self.raw_data[5:] * 2).fillna(0) assert_frame_equal(results['dv1_nan'].unstack(), expected_1_nan) expected_5_nan = rolling_mean( (self.raw_data_with_nans * self.raw_data * 2).fillna(0), window=5)[5:] assert_frame_equal(results['dv5_nan'].unstack(), expected_5_nan)
def make_pipeline(): # universe = make_china_equity_universe( # target_size = 100, # mask = default_china_equity_universe_mask(['000001']), # max_group_weight= 0.01, # smoothing_func = lambda f: f.downsample('week_start'), # ) dollar_volume = AverageDollarVolume(window_length=1) high_dollar_volume = dollar_volume.percentile_between(N, 100) recent_returns = Returns(window_length=N, mask=high_dollar_volume) low_returns = recent_returns.percentile_between(0, 10) high_returns = recent_returns.percentile_between(N, 100) pipe_columns = { 'low_returns': low_returns, 'high_returns': high_returns, 'recent_returns': recent_returns, 'dollar_volume': dollar_volume } pipe_screen = (low_returns | high_returns) pipe = Pipeline(columns=pipe_columns, screen=pipe_screen) return pipe
def make_pipeline(): """ Create our pipeline. """ # Base universe set to the Q1500US. base_universe = AverageDollarVolume(window_length=20).percentile_between(70, 100) latest_close = USEquityPricing.close.latest # 14-day RSI rsi_14 = RSI( inputs=[USEquityPricing.close], window_length=14, mask=base_universe ) # 20-day, 2 standard deviation Bollinger bands bbLow, bbMid, bbHigh = BollingerBands( inputs=[USEquityPricing.close], window_length=10, k=2, mask=base_universe ) rsiOverbought = rsi_14 > 70 rsiOversold = rsi_14 < 30 bbOverbought = latest_close > bbHigh bbOversold = latest_close < bbLow overbought = rsiOverbought | bbOverbought oversold = rsiOversold | bbOversold # Filter to select securities to short. shorts = overbought # Filter to select securities to long. longs = oversold # 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), )
class TradingVolume(CustomFactor): """ Trading volume is computed as the total dollar amount of trading in the stock over the trailing month as a percent of total market capitalization. """ #inputs = [MonthlyDollarVolume(), MarketCap()] inputs = [AverageDollarVolume(window_length=20), MarketCap()] window_safe = True window_length = 1 def compute(self, today, assets, out, monthly_dollar_volume, market_cap): length = self.window_length out[:] = monthly_dollar_volume[-length] / market_cap[-length]
def TradableStocksUS(market_cap_filter=False): """ Returns a Pipeline filter of tradable stocks, defined as: - Common stocks only (no preferred stocks, ADRs, LPs, or ETFs) - Primary shares only - 200-day average dollar volume >= $2.5M - price >= $5 - 200 continuous days of price and volume. If market_cap_filter=True, also requires market cap > $500M. """ # Equities listed as common stock (not preferred stock, ETF, ADR, LP, etc) common_stock = master.SecuritiesMaster.usstock_SecurityType2.latest.eq( 'Common Stock') # Filter for primary share equities; primary shares can be identified by a # null usstock_PrimaryShareSid field (i.e. no pointer to a primary share) is_primary_share = master.SecuritiesMaster.usstock_PrimaryShareSid.latest.isnull( ) # combine the security type filters to begin forming our universe tradable_stocks = common_stock & is_primary_share # also require high dollar volume tradable_stocks = AverageDollarVolume(window_length=200, mask=tradable_stocks) >= 2.5e6 # also require price > $5. Note that we use Latest(...) instead of EquityPricing.close.latest # so that we can pass a mask tradable_stocks = Latest([EquityPricing.close], mask=tradable_stocks) > 5 # also require no missing data for 200 days tradable_stocks = AllPresent(inputs=[EquityPricing.close], window_length=200, mask=tradable_stocks) tradable_stocks = All([EquityPricing.volume.latest > 0], window_length=200, mask=tradable_stocks) if market_cap_filter: # also require market cap over $500M tradable_stocks = Latest([ sharadar.Fundamentals.slice(dimension='ARQ', period_offset=0).MARKETCAP ], mask=tradable_stocks) >= 500e6 return tradable_stocks
def initialize(context): ws.send(msg_placeholder % "Simulation Start") pipe = Pipeline() attach_pipeline(pipe, "volume_pipeline") # 100 day average dollar volume factor dollar_volume = AverageDollarVolume(window_length=100) pipe.add(dollar_volume, "100_day_dollar_volume") # filter out only the top stocks by dollar volume high_dollar_volume = dollar_volume.percentile_between(99, 100) pipe.set_screen(high_dollar_volume) # set the global variables context.dev_multiplier = 2 context.max_notional = 1000000 context.min_notional = -1000000 context.days_traded = 0 ws.send(msg_placeholder % "Pipeline filter attached") schedule_function(func=choose_and_order, date_rule=date_rules.every_day())
def universe_filters(): # Equities with an average daily volume greater than 750000. high_volume = AverageDollarVolume(window_length=66) > 1500000 # Equities for which morningstar's most recent Market Cap value is above $300 # Equities whose exchange id does not start with OTC (Over The Counter). # startswith() is a new method available only on string-dtype Classifiers. # It returns a Filter. #not_otc = ~mstar.share_class_reference.exchange_id.latest.startswith('OTC') # Equities whose symbol (according to morningstar) ends with .WI # This generally indicates a "When Issued" offering. # endswith() works similarly to startswith(). #not_wi = ~mstar.share_class_reference.symbol.latest.endswith('.WI') # Equities whose company name ends with 'LP' or a similar string. # The .matches() method uses the standard library `re` module to match # against a regular expression. #not_lp_name = ~mstar.company_reference.standard_name.latest.matches('.* L[\\. ]?P\.?$') # Equities with a null entry for the balance_sheet.limited_partnership field. # This is an alternative way of checking for LPs. #not_lp_balance_sheet = mstar.balance_sheet.limited_partnership.latest.isnull() # Highly liquid assets only. Also eliminates IPOs in the past 12 months # Use new average dollar volume so that unrecorded days are given value 0 # and not skipped over # S&P Criterion #liquid = ADV_adj() #liq_f = liquid > 25000 # Add logic when global markets supported # S&P Criterion #domicile = True #universe_filter = (high_volume & primary_share & have_market_cap & not_depositary & # common_stock & not_otc & not_wi & not_lp_name & not_lp_balance_sheet & # liquid & domicile) #universe_filter = (high_volume & liq_f) universe_filter = (high_volume) return universe_filter
def make_pipeline(): """ Create a pipeline with the following rules: screen - common stocks only - must be liquid (top 10% by dollar volume) - must be above 20-day moving average - must not be too cheap or too expensive columns - 20-day moving average - prior low - standard deviation of closing prices """ mavg = SimpleMovingAverage(window_length=20, inputs=[EquityPricing.close]) are_common_stocks = SecuritiesMaster.usstock_SecurityType2.latest.eq( "Common Stock") are_liquid = AverageDollarVolume(window_length=30).percentile_between( 90, 100) are_above_mavg = EquityPricing.close.latest > mavg are_not_too_cheap = EquityPricing.close.latest > 10 are_not_too_expensive = EquityPricing.close.latest < 2000 pipeline = Pipeline(columns={ "mavg": mavg, "prior_low": EquityPricing.low.latest, "std": ExponentialWeightedMovingStdDev(inputs=[EquityPricing.close], window_length=63, decay_rate=0.99) }, screen=(are_common_stocks & are_liquid & are_above_mavg & are_not_too_cheap & are_not_too_expensive)) return pipeline
def get_universe(self, start_date, end_date, assets=None, min_avg_dollar_vol=1e6, min_price=4.0): adv = AverageDollarVolume(window_length=20) latest_close = USEquityPricing.close.latest # min_market_cap = market_cap >= 100e6 # Need market cap data min_adv = (adv >= min_avg_dollar_vol) min_latest_close = (latest_close >= min_price) screen = (min_adv & min_latest_close) if assets is not None: screen = (StaticAssets(assets) & screen) pipeline = Pipeline(columns={'latest_close': latest_close}, screen=screen) df = self._run_pipeline(pipeline, start_date, end_date) df.drop(['latest_close'], axis=1, inplace=True) return df
def make_pipeline(asset_finder): hs300 = ts.get_hs300s()['code'] private_universe = private_universe_mask(hs300.tolist(), asset_finder=asset_finder) #private_universe = private_universe_mask(['000001','000002','000005'],asset_finder=asset_finder) ###################################################################################################### returns = Returns(inputs=[USEquityPricing.close], window_length=5, mask=private_universe) # 预测一周数据 ###################################################################################################### ep = 1 / Fundamental(mask=private_universe, asset_finder=asset_finder).pe bp = 1 / Fundamental(mask=private_universe, asset_finder=asset_finder).pb bvps = Fundamental(mask=private_universe, asset_finder=asset_finder).bvps market = Fundamental(mask=private_universe, asset_finder=asset_finder).outstanding totals = Fundamental(mask=private_universe, asset_finder=asset_finder).totals totalAssets = Fundamental(mask=private_universe, asset_finder=asset_finder).totalAssets fixedAssets = Fundamental(mask=private_universe, asset_finder=asset_finder).fixedAssets esp = Fundamental(mask=private_universe, asset_finder=asset_finder).esp rev = Fundamental(mask=private_universe, asset_finder=asset_finder).rev profit = Fundamental(mask=private_universe, asset_finder=asset_finder).profit gpr = Fundamental(mask=private_universe, asset_finder=asset_finder).gpr npr = Fundamental(mask=private_universe, asset_finder=asset_finder).npr rev10 = Returns(inputs=[USEquityPricing.close], window_length=10, mask=private_universe) vol10 = AverageDollarVolume(window_length=20, mask=private_universe) rev20 = Returns(inputs=[USEquityPricing.close], window_length=20, mask=private_universe) vol20 = AverageDollarVolume(window_length=20, mask=private_universe) rev30 = Returns(inputs=[USEquityPricing.close], window_length=30, mask=private_universe) vol30 = AverageDollarVolume(window_length=20, mask=private_universe) illiq22 = ILLIQ(window_length=22, mask=private_universe) illiq5 = ILLIQ(window_length=5, mask=private_universe) rsi5 = RSI(window_length=5, mask=private_universe) rsi22 = RSI(window_length=22, mask=private_universe) mom5 = Momentum(window_length=5, mask=private_universe) mom22 = Momentum(window_length=22, mask=private_universe) sector = get_sector(asset_finder=asset_finder, mask=private_universe) ONEHOTCLASS, sector_indict_keys = get_sector_by_onehot( asset_finder=asset_finder, mask=private_universe) pipe_columns = { 'ep': ep.zscore(groupby=sector).downsample('month_start'), 'bp': bp.zscore(groupby=sector).downsample('month_start'), 'bvps': bvps.zscore(groupby=sector).downsample('month_start'), 'market_cap': market.zscore(groupby=sector).downsample('month_start'), 'totals': totals.zscore(groupby=sector).downsample('month_start'), 'totalAssets': totalAssets.zscore(groupby=sector).downsample('month_start'), 'fixedAssets': fixedAssets.zscore(groupby=sector).downsample('month_start'), 'esp': esp.zscore(groupby=sector).downsample('month_start'), 'rev': rev.zscore(groupby=sector).downsample('month_start'), 'profit': profit.zscore(groupby=sector).downsample('month_start'), 'gpr': gpr.zscore(groupby=sector).downsample('month_start'), 'npr': npr.zscore(groupby=sector).downsample('month_start'), 'vol10': vol10.zscore(groupby=sector).downsample('week_start'), 'rev10': rev10.zscore(groupby=sector).downsample('week_start'), 'vol20': vol20.zscore(groupby=sector).downsample('week_start'), 'rev20': rev20.zscore(groupby=sector).downsample('week_start'), 'vol30': vol30.zscore(groupby=sector).downsample('week_start'), 'rev30': rev30.zscore(groupby=sector).downsample('week_start'), 'ILLIQ5': illiq5.zscore(groupby=sector).downsample('week_start'), 'ILLIQ22': illiq22.zscore(groupby=sector).downsample('week_start'), 'mom5': mom5.zscore(groupby=sector).downsample('week_start'), 'mom22': mom22.zscore(groupby=sector).downsample('week_start'), 'rsi5': rsi5.zscore(groupby=sector).downsample('week_start'), 'rsi22': rsi22.zscore(groupby=sector).downsample('week_start'), #'rsi22': rsi22.zscore(groupby=sector, mask=rsi22.percentile_between(1, 99)), ####################################################################################################################### # 'ILLIQ5-2' : illiq5.zscore(groupby=quantiles([illiq5],bins = 10,mask = private_universe)).downsample('week_start'), # 'ILLIQ22-2': illiq22.zscore(groupby=quantiles([illiq22],bins = 10,mask = private_universe)).downsample('week_start'), # 'ILLIQ5-2': illiq5.zscore(groupby=market.quantiles(bins=10, mask=private_universe)).downsample('week_start'), # 'ILLIQ22-2': illiq22.zscore(groupby=market.quantiles(bins=10, mask=private_universe)).downsample('week_start'), ############################################################################################################################# 'returns': returns.downsample('week_start'), } pipe = Pipeline( columns=pipe_columns, screen=private_universe, ) i = 0 for c in ONEHOTCLASS: pipe.add(c, sector_indict_keys[i]) i += 1 return pipe
print('Data Registered') # ## Build Pipeline Engine # We'll be using Zipline's pipeline package to access our data for this project. To use it, we must build a pipeline engine. Run the cell below to build the engine. # In[5]: from zipline.pipeline import Pipeline from zipline.pipeline.factors import AverageDollarVolume from zipline.utils.calendars import get_calendar universe = AverageDollarVolume(window_length=120).top(500) trading_calendar = get_calendar('NYSE') bundle_data = bundles.load(project_helper.EOD_BUNDLE_NAME) engine = project_helper.build_pipeline_engine(bundle_data, trading_calendar) # ### View Data # With the pipeline engine built, let's get the stocks at the end of the period in the universe we're using. We'll use these tickers to generate the returns data for the our risk model. # In[6]: universe_end_date = pd.Timestamp('2016-01-05', tz='UTC') universe_tickers = engine .run_pipeline( Pipeline(screen=universe),
def TradableStocksUS(min_percentile=30): return ((StocksUS()) & (AverageDollarVolume(window_length=200).percentile_between( min_percentile, 100.0, mask=StocksUS())) & (MarketCap().percentile_between( min_percentile, 100.0, mask=StocksUS())))
ingest_func = bundles.csvdir.csvdir_equities(['daily'], project_helper.EOD_BUNDLE_NAME) bundles.register(project_helper.EOD_BUNDLE_NAME, ingest_func) print('Data Registered') # ### Build Pipeline Engine # We'll be using Zipline's pipeline package to access our data for this project. To use it, we must build a pipeline engine. Run the cell below to build the engine. # In[43]: from zipline.pipeline import Pipeline from zipline.pipeline.factors import AverageDollarVolume from zipline.utils.calendars import get_calendar universe = AverageDollarVolume(window_length=120).top(500) trading_calendar = get_calendar('NYSE') bundle_data = bundles.load(project_helper.EOD_BUNDLE_NAME) engine = project_helper.build_pipeline_engine(bundle_data, trading_calendar) # #### View Data # With the pipeline engine built, let's get the stocks at the end of the period in the universe we're using. # In[46]: universe_end_date = pd.Timestamp('2016-01-05', tz='UTC') universe_tickers = engine .run_pipeline( Pipeline(screen=universe), universe_end_date, universe_end_date)\
def make_pipeline(asset_finder, algo_mode): private_universe = private_universe_mask(hs300.tolist(), asset_finder=asset_finder) #private_universe = private_universe_mask( ['000005'],asset_finder=asset_finder) ###private_universe = private_universe_mask( ['000002','000005'],asset_finder=asset_finder) #private_universe = private_universe_mask( ['000001','000002','000005'],asset_finder=asset_finder) #private_universe = private_universe_mask( ['000001'],asset_finder=asset_finder) #print private_universe_mask(['000001','000002','000005'],asset_finder=asset_finder) ###################################################################################################### returns = Returns(inputs=[USEquityPricing.close], window_length=5, mask=private_universe) # 预测一周数据 ###################################################################################################### pe = Fundamental(mask=private_universe, asset_finder=asset_finder).pe pb = Fundamental(mask=private_universe, asset_finder=asset_finder).pb bvps = Fundamental(mask=private_universe, asset_finder=asset_finder).bvps market = Fundamental(mask=private_universe, asset_finder=asset_finder).outstanding totals = Fundamental(mask=private_universe, asset_finder=asset_finder).totals totalAssets = Fundamental(mask=private_universe, asset_finder=asset_finder).totalAssets fixedAssets = Fundamental(mask=private_universe, asset_finder=asset_finder).fixedAssets esp = Fundamental(mask=private_universe, asset_finder=asset_finder).esp rev = Fundamental(mask=private_universe, asset_finder=asset_finder).rev profit = Fundamental(mask=private_universe, asset_finder=asset_finder).profit gpr = Fundamental(mask=private_universe, asset_finder=asset_finder).gpr npr = Fundamental(mask=private_universe, asset_finder=asset_finder).npr rev10 = Returns(inputs=[USEquityPricing.close], window_length=10, mask=private_universe) vol10 = AverageDollarVolume(window_length=20, mask=private_universe) rev20 = Returns(inputs=[USEquityPricing.close], window_length=20, mask=private_universe) vol20 = AverageDollarVolume(window_length=20, mask=private_universe) rev30 = Returns(inputs=[USEquityPricing.close], window_length=30, mask=private_universe) vol30 = AverageDollarVolume(window_length=20, mask=private_universe) illiq22 = ILLIQ(window_length=22, mask=private_universe) illiq5 = ILLIQ(window_length=5, mask=private_universe) rsi5 = RSI(window_length=5, mask=private_universe) rsi22 = RSI(window_length=22, mask=private_universe) mom5 = Momentum(window_length=5, mask=private_universe) mom22 = Momentum(window_length=22, mask=private_universe) sector = get_sector(asset_finder=asset_finder, mask=private_universe) ONEHOTCLASS, sector_indict_keys = get_sector_by_onehot( asset_finder=asset_finder, mask=private_universe) pipe_columns = { 'pe': pe.zscore(groupby=sector).downsample('month_start'), 'pb': pb.zscore(groupby=sector).downsample('month_start'), 'bvps': bvps.zscore(groupby=sector).downsample('month_start'), 'market_cap': market.zscore(groupby=sector).downsample('month_start'), 'totals': totals.zscore(groupby=sector).downsample('month_start'), 'totalAssets': totalAssets.zscore(groupby=sector).downsample('month_start'), 'fixedAssets': fixedAssets.zscore(groupby=sector).downsample('month_start'), 'esp': esp.zscore(groupby=sector).downsample('month_start'), 'rev': rev.zscore(groupby=sector).downsample('month_start'), 'profit': profit.zscore(groupby=sector).downsample('month_start'), 'gpr': gpr.zscore(groupby=sector).downsample('month_start'), 'npr': npr.zscore(groupby=sector).downsample('month_start'), 'vol10': vol10.zscore(groupby=sector).downsample('week_start'), 'rev10': rev10.zscore(groupby=sector).downsample('week_start'), 'vol20': vol20.zscore(groupby=sector).downsample('week_start'), 'rev20': rev20.zscore(groupby=sector).downsample('week_start'), 'vol30': vol30.zscore(groupby=sector).downsample('week_start'), 'rev30': rev30.zscore(groupby=sector).downsample('week_start'), 'ILLIQ5': illiq5.zscore(groupby=sector).downsample('week_start'), 'ILLIQ22': illiq22.zscore(groupby=sector).downsample('week_start'), 'mom5': mom5.zscore(groupby=sector).downsample('week_start'), 'mom22': mom22.zscore(groupby=sector).downsample('week_start'), 'rsi5': rsi5.zscore(groupby=sector).downsample('week_start'), 'rsi22': rsi22.zscore(groupby=sector).downsample('week_start'), } from collections import OrderedDict factors_pipe = OrderedDict() factors_pipe['Returns'] = returns factors_pipe['Returns'].window_safe = True idx = 0 sort_keys = sorted(pipe_columns) for key in sort_keys: #print(key) factors_pipe[key] = pipe_columns[key] factors_pipe[key].window_safe = True idx += 1 if idx == 100: break #for name, f in pipe_columns.items(): # f.window_safe = True # factors_pipe[name] = f # print (name,f) # idx += 1 # if idx == 1: # break i = 0 for c in ONEHOTCLASS: c.window_safe = True factors_pipe[sector_indict_keys[i]] = c #print (c,sector_indict_keys[i]) i += 1 predict = BasicFactorRegress(inputs=factors_pipe.values(), window_length=252, mask=private_universe, n_fwd_days=5, algo_mode=algo_mode, cross=False) predict_rank = predict.rank(mask=private_universe) longs = predict_rank.top(NUM_LONG_POSITIONS) shorts = predict_rank.bottom(NUM_SHORT_POSITIONS) long_short_screen = (longs | shorts) #TODO sector onehot pipe_final_columns = { 'Predict Factor': predict.downsample('week_start'), 'longs': longs.downsample('week_start'), 'shorts': shorts.downsample('week_start'), 'predict_rank': predict_rank.downsample('week_start'), } pipe = Pipeline( columns=pipe_final_columns, screen=long_short_screen, ) return pipe
def test_mean_reversion_5day_sector_neutral_smoothed(fn): column_name = "Mean_Reversion_5Day_Sector_Neutral_Smoothed" start_date_str = "2015-01-05" end_date_str = "2015-01-07" # Build engine trading_calendar = get_calendar("NYSE") bundle_data = bundles.load(project_helper.EOD_BUNDLE_NAME) engine = project_helper.build_pipeline_engine(bundle_data, trading_calendar) # Build pipeline universe_window_length = 2 universe_asset_count = 4 universe = AverageDollarVolume( window_length=universe_window_length).top(universe_asset_count) pipeline = Pipeline(screen=universe) run_pipeline_args = { "pipeline": pipeline, "start_date": pd.Timestamp(start_date_str, tz="utc"), "end_date": pd.Timestamp(end_date_str, tz="utc"), } fn_inputs = { "window_length": 3, "universe": universe, "sector": project_helper.Sector(), } fn_correct_outputs = OrderedDict([( "pipline_out", pd.DataFrame( [ 0.44721360, 1.34164079, -1.34164079, -0.44721360, 1.34164079, 0.44721360, -1.34164079, -0.44721360, 0.44721360, 1.34164079, -1.34164079, -0.44721360, ], engine.run_pipeline(**run_pipeline_args).index, [column_name], ), )]) print("Running Integration Test on pipeline:") print("> start_dat = pd.Timestamp('{}', tz='utc')".format(start_date_str)) print("> end_date = pd.Timestamp('{}', tz='utc')".format(end_date_str)) print("> universe = AverageDollarVolume(window_length={}).top({})".format( universe_window_length, universe_asset_count)) print("> factor = {}(".format(fn.__name__)) print(" window_length={},".format(fn_inputs["window_length"])) print(" universe=universe,") print(" sector=project_helper.Sector())") print("> pipeline.add(factor, '{}')".format(column_name)) print("> engine.run_pipeline(pipeline, start_dat, end_date)") print("") pipeline.add(fn(**fn_inputs), column_name) assert_output( engine.run_pipeline, run_pipeline_args, fn_correct_outputs, check_parameter_changes=False, )
def run_data_pipeline(engine, universe, start_date, end_date): pipeline = Pipeline(screen=universe) sector = Sector() # Alpha Factors : pipeline.add(DownsideRisk(), 'Downside Risk (Sortino Ratio)') pipeline.add(Vol3M(), '3 Month Volatility') pipeline.add(momentum_1yr(252, universe, sector), 'Momentum_1YR') pipeline.add( mean_reversion_5day_sector_neutral_smoothed(20, universe, sector), 'Mean_Reversion_Sector_Neutral_Smoothed') pipeline.add(overnight_sentiment_smoothed(2, 10, universe), 'Overnight_Sentiment_Smoothed') pipeline.add(rsi_sector_neutral(15, universe, sector), 'RSI_Sector_Neutral_15d') pipeline.add(rsi_sector_neutral(30, universe, sector), 'RSI_Sector_Neutral_30d') beta_factor = (RegressionAgainstTime(mask=universe).beta.rank().zscore()) gamma_factor = (RegressionAgainstTime(mask=universe).gamma.rank().zscore()) conditional_factor = (beta_factor * gamma_factor).rank().zscore() pipeline.add(beta_factor, 'time_beta') pipeline.add(gamma_factor, 'time_gamma') pipeline.add(conditional_factor, 'conditional_factor') # Universal Quant Features : pipeline.add( AnnualizedVolatility(window_length=20, mask=universe).rank().zscore(), 'volatility_20d') pipeline.add( AnnualizedVolatility(window_length=120, mask=universe).rank().zscore(), 'volatility_120d') pipeline.add( AverageDollarVolume(window_length=20, mask=universe).rank().zscore(), 'adv_20d') pipeline.add( AverageDollarVolume(window_length=120, mask=universe).rank().zscore(), 'adv_120d') pipeline.add(sector, 'sector_code') # Regime Features : pipeline.add( SimpleMovingAverage(inputs=[MarketDispersion(mask=universe)], window_length=20), 'dispersion_20d') pipeline.add( SimpleMovingAverage(inputs=[MarketDispersion(mask=universe)], window_length=120), 'dispersion_120d') pipeline.add(MarketVolatility(window_length=20), 'market_vol_20d') pipeline.add(MarketVolatility(window_length=120), 'market_vol_120d') # Target # Let's try to predict the go forward 1-week return. When doing this, it's important to quantize the target. The factor we create is the trailing 5-day return pipeline.add( Returns(window_length=5, mask=universe).quantiles(2), 'return_5d') pipeline.add( Returns(window_length=5, mask=universe).quantiles(25), 'return_5d_p') # Running the Pipeline all_factors = engine.run_pipeline(pipeline, start_date, end_date) # Computing Date Features all_factors = compute_date_features(all_factors, start_date, end_date) # One Hot Encoding Sectors all_factors = one_hot_encode_sectors(all_factors) # Shifted Target For Training The Model all_factors['target'] = all_factors.groupby(level=1)['return_5d'].shift(-5) return all_factors