def test_tsi2(self): target = 'TSI' result = tsi(**self._params) pd.testing.assert_series_equal(self._df[target].tail(), result.tail(), check_names=False, check_less_precise=True)
def get_ml_feature(self, symbol, prices=None, cutoff=None): if prices: price = prices.get(symbol, 1E10) vix = prices['^VIX'] else: price = self.closes[symbol][cutoff] vix = self.closes['^VIX'][cutoff] if cutoff: close = self.closes[symbol][cutoff - DAYS_IN_A_YEAR:cutoff] high = np.array( self.hists[symbol].get('High')[cutoff - DAYS_IN_A_YEAR:cutoff]) low = np.array( self.hists[symbol].get('Low')[cutoff - DAYS_IN_A_YEAR:cutoff]) else: close = self.closes[symbol][-DAYS_IN_A_YEAR:] high = np.array(self.hists[symbol].get('High')[-DAYS_IN_A_YEAR:]) low = np.array(self.hists[symbol].get('Low')[-DAYS_IN_A_YEAR:]) # Basic stats day_range_change = price / np.max(close[-DATE_RANGE:]) - 1 today_change = price / close[-1] - 1 yesterday_change = close[-1] / close[-2] - 1 day_before_yesterday_change = close[-2] / close[-3] - 1 twenty_day_change = price / close[-20] - 1 year_high_change = price / np.max(close) - 1 year_low_change = price / np.min(close) - 1 all_changes = [ close[t + 1] / close[t] - 1 for t in range(len(close) - 1) if close[t + 1] > 0 and close[t] > 0 ] # Technical indicators close = np.append(close, price) high = np.append(high, price) low = np.append(low, price) pd_close = pd.Series(close) pd_high = pd.Series(high) pd_low = pd.Series(low) rsi = momentum.rsi(pd_close).values[-1] macd_rate = trend.macd_diff(pd_close).values[-1] / price wr = momentum.wr(pd_high, pd_low, pd_close).values[-1] tsi = momentum.tsi(pd_close).values[-1] feature = { 'Today_Change': today_change, 'Yesterday_Change': yesterday_change, 'Day_Before_Yesterday_Change': day_before_yesterday_change, 'Twenty_Day_Change': twenty_day_change, 'Day_Range_Change': day_range_change, 'Year_High_Change': year_high_change, 'Year_Low_Change': year_low_change, 'Change_Average': np.mean(all_changes), 'Change_Variance': np.var(all_changes), 'RSI': rsi, 'MACD_Rate': macd_rate, 'WR': wr, 'TSI': tsi, 'VIX': vix } return feature
def Feature_Extraction_Momentum(df): df = SOK(df) df = SOD(df) df = SOJ(df) df = MACD(df) df = MACD_Signal(df) df = MACD_Hist(df) df['RSI'] = tas.RSI(df['close'].values) df['ROC'] = tas.ROC(df['close'].values) df['WillR'] = tas.WILLR(df['high'].values, df['low'].values, df['close'].values) df['CCI'] = tas.CCI(df['high'].values, df['low'].values, df['close'].values) df['TSI'] = tsi(df['close'], window_slow=25, window_fast=13) df['ADX'] = tas.ADX(df['high'].values, df['low'].values, df['close'].values) df['MFI'] = tas.MFI(df['high'], df['low'], df['close'], df['volume']) df['MOM'] = tas.MOM(df['close']) df['TRIX'] = tas.TRIX(df['close']) df['ULTOSC'] = tas.ULTOSC(df['high'], df['low'], df['close']) df = df.fillna(0) return df
def engineer_data_over_single_interval(df: pd.DataFrame, indicators: list, ticker: str = "", rsi_n: int = 14, cmo_n: int = 7, macd_fast: int = 12, macd_slow: int = 26, macd_sign: int = 9, roc_n: int = 12, cci_n: int = 20, dpo_n: int = 20, cmf_n: int = 20, adx_n: int = 14, mass_index_low: int = 9, mass_index_high: int = 25, trix_n: int = 15, stochastic_oscillator_n: int = 14, stochastic_oscillator_sma_n: int = 3, ultimate_oscillator_short_n: int = 7, ultimate_oscillator_medium_n: int = 14, ultimate_oscillator_long_n: int = 28, ao_short_n: int = 5, ao_long_n: int = 34, kama_n: int = 10, tsi_high_n: int = 25, tsi_low_n: int = 13, eom_n: int = 14, force_index_n: int = 13, ichimoku_low_n: int = 9, ichimoku_medium_n: int = 26): from ta.momentum import rsi, wr, roc, ao, stoch, uo, kama, tsi from ta.trend import macd, macd_signal, cci, dpo, adx, mass_index, trix, ichimoku_a from ta.volume import chaikin_money_flow, acc_dist_index, ease_of_movement, force_index # Momentum Indicators if Indicators.RELATIVE_STOCK_INDEX in indicators: Logger.console_log(message="Calculating " + Indicators.RELATIVE_STOCK_INDEX.value + " for stock " + ticker, status=Logger.LogStatus.EMPHASIS) df[Indicators.RELATIVE_STOCK_INDEX.value] = rsi(close=df['close'], n=rsi_n) if Indicators.WILLIAMS_PERCENT_RANGE in indicators: Logger.console_log(message="Calculating " + Indicators.WILLIAMS_PERCENT_RANGE.value + " for stock " + ticker, status=Logger.LogStatus.EMPHASIS) df[Indicators.WILLIAMS_PERCENT_RANGE.value] = wr( df['high'], df['low'], df['close']) if Indicators.CHANDE_MOMENTUM_OSCILLATOR in indicators: Logger.console_log(message="Calculating " + Indicators.CHANDE_MOMENTUM_OSCILLATOR.value + " for stock " + ticker, status=Logger.LogStatus.EMPHASIS) df[Indicators.CHANDE_MOMENTUM_OSCILLATOR. value] = chande_momentum_oscillator(close_data=df['close'], period=cmo_n) if Indicators.RATE_OF_CHANGE in indicators: Logger.console_log(message="Calculating " + Indicators.RATE_OF_CHANGE.value + " for stock " + ticker, status=Logger.LogStatus.EMPHASIS) df[Indicators.RATE_OF_CHANGE.value] = roc(close=df['close'], n=roc_n) if Indicators.STOCHASTIC_OSCILLATOR in indicators: Logger.console_log(message="Calculating " + Indicators.STOCHASTIC_OSCILLATOR.value + " for stock " + ticker, status=Logger.LogStatus.EMPHASIS) df[Indicators.STOCHASTIC_OSCILLATOR.value] = stoch( high=df['high'], low=df['low'], close=df['close'], n=stochastic_oscillator_n, d_n=stochastic_oscillator_sma_n) if Indicators.ULTIMATE_OSCILLATOR in indicators: Logger.console_log(message="Calculating " + Indicators.ULTIMATE_OSCILLATOR.value + " for stock " + ticker, status=Logger.LogStatus.EMPHASIS) df[Indicators.ULTIMATE_OSCILLATOR.value] = uo( high=df['high'], low=df['low'], close=df['close'], s=ultimate_oscillator_short_n, m=ultimate_oscillator_medium_n, len=ultimate_oscillator_long_n) if Indicators.AWESOME_OSCILLATOR in indicators: Logger.console_log(message="Calculating " + Indicators.AWESOME_OSCILLATOR.value + " for stock " + ticker, status=Logger.LogStatus.EMPHASIS) df[Indicators.AWESOME_OSCILLATOR.value] = ao(high=df['high'], low=df['low'], s=ao_short_n, len=ao_long_n) if Indicators.KAUFMAN_ADAPTIVE_MOVING_AVERAGE in indicators: Logger.console_log(message="Calculating " + Indicators.KAUFMAN_ADAPTIVE_MOVING_AVERAGE.value + " for stock " + ticker, status=Logger.LogStatus.EMPHASIS) df[Indicators.KAUFMAN_ADAPTIVE_MOVING_AVERAGE.value] = kama( close=df['close'], n=kama_n) if Indicators.TRUE_STRENGTH_INDEX in indicators: Logger.console_log(message="Calculating " + Indicators.TRUE_STRENGTH_INDEX.value + " for stock " + ticker, status=Logger.LogStatus.EMPHASIS) df[Indicators.TRUE_STRENGTH_INDEX.value] = tsi(close=df['close'], r=tsi_high_n, s=tsi_low_n) # Trend Indicator if Indicators.MOVING_AVERAGE_CONVERGENCE_DIVERGENCE in indicators: Logger.console_log( message="Calculating " + Indicators.MOVING_AVERAGE_CONVERGENCE_DIVERGENCE.value + " for stock " + ticker, status=Logger.LogStatus.EMPHASIS) df[Indicators.MOVING_AVERAGE_CONVERGENCE_DIVERGENCE.value] = macd(close=df['close'], n_slow=macd_slow, n_fast=macd_fast) - \ macd_signal(close=df['close'], n_slow=macd_slow, n_fast=macd_fast, n_sign=macd_sign) if Indicators.COMMODITY_CHANNEL_INDEX in indicators: Logger.console_log(message="Calculating " + Indicators.COMMODITY_CHANNEL_INDEX.value + " for stock " + ticker, status=Logger.LogStatus.EMPHASIS) df[Indicators.COMMODITY_CHANNEL_INDEX.value] = cci(high=df['high'], low=df['low'], close=df['close'], n=cci_n) if Indicators.DETRENDED_PRICE_OSCILLATOR in indicators: Logger.console_log(message="Calculating " + Indicators.DETRENDED_PRICE_OSCILLATOR.value + " for stock " + ticker, status=Logger.LogStatus.EMPHASIS) df[Indicators.DETRENDED_PRICE_OSCILLATOR.value] = dpo( close=df['close'], n=dpo_n) if Indicators.AVERAGE_DIRECTIONAL_INDEX in indicators: Logger.console_log(message="Calculating " + Indicators.AVERAGE_DIRECTIONAL_INDEX.value + " for stock " + ticker, status=Logger.LogStatus.EMPHASIS) df[Indicators.AVERAGE_DIRECTIONAL_INDEX.value] = adx(high=df['high'], low=df['low'], close=df['close'], n=adx_n) if Indicators.MASS_INDEX in indicators: Logger.console_log(message="Calculating " + Indicators.MASS_INDEX.value + " for stock " + ticker, status=Logger.LogStatus.EMPHASIS) df[Indicators.MASS_INDEX.value] = mass_index(high=df['high'], low=df['low'], n=mass_index_low, n2=mass_index_high) if Indicators.TRIPLE_EXPONENTIALLY_SMOOTHED_MOVING_AVERAGE in indicators: Logger.console_log( message="Calculating " + Indicators.TRIPLE_EXPONENTIALLY_SMOOTHED_MOVING_AVERAGE.value + " for stock " + ticker, status=Logger.LogStatus.EMPHASIS) df[Indicators.TRIPLE_EXPONENTIALLY_SMOOTHED_MOVING_AVERAGE. value] = trix(close=df['close'], n=trix_n) if Indicators.ICHIMOKU_A in indicators: Logger.console_log(message="Calculating " + Indicators.ICHIMOKU_A.value + " for stock " + ticker, status=Logger.LogStatus.EMPHASIS) df[Indicators.ICHIMOKU_A.value] = ichimoku_a(high=df['high'], low=df['low'], n1=ichimoku_low_n, n2=ichimoku_medium_n) # Volume Indicator if Indicators.CHAIKIN_MONEY_FLOW in indicators: Logger.console_log(message="Calculating " + Indicators.CHAIKIN_MONEY_FLOW.value + " for stock " + ticker, status=Logger.LogStatus.EMPHASIS) df[Indicators.CHAIKIN_MONEY_FLOW.value] = chaikin_money_flow( high=df['high'], low=df['low'], close=df['close'], volume=df['volume'], n=cmf_n) if Indicators.ACCUMULATION_DISTRIBUTION_INDEX in indicators: Logger.console_log(message="Calculating " + Indicators.ACCUMULATION_DISTRIBUTION_INDEX.value + " for stock " + ticker, status=Logger.LogStatus.EMPHASIS) df[Indicators.ACCUMULATION_DISTRIBUTION_INDEX.value] = acc_dist_index( high=df['high'], low=df['low'], close=df['close'], volume=df['volume']) if Indicators.EASE_OF_MOVEMENT in indicators: Logger.console_log(message="Calculating " + Indicators.EASE_OF_MOVEMENT.value + " for stock " + ticker, status=Logger.LogStatus.EMPHASIS) df[Indicators.EASE_OF_MOVEMENT.value] = ease_of_movement( high=df['high'], low=df['low'], volume=df['volume'], n=eom_n) if Indicators.FORCE_INDEX in indicators: Logger.console_log(message="Calculating " + Indicators.FORCE_INDEX.value + " for stock " + ticker, status=Logger.LogStatus.EMPHASIS) df[Indicators.FORCE_INDEX.value] = force_index(close=df['close'], volume=df['volume'], n=force_index_n)
def get_ml_feature(self, symbol, prices=None, cutoff=None): feature = {} if prices: price = prices.get(symbol, 1E10) vix = prices['^VIX'] else: price = self.closes[symbol][cutoff] vix = self.closes['^VIX'][cutoff] if cutoff: close = self.closes[symbol][cutoff - DAYS_IN_A_YEAR:cutoff] volume = self.volumes[symbol][cutoff - DAYS_IN_A_YEAR:cutoff] else: close = self.closes[symbol][-DAYS_IN_A_YEAR:] volume = self.volumes[symbol][-DAYS_IN_A_YEAR:] close = np.append(close, price) # Log returns feature['Day_1_Return'] = np.log(close[-1] / close[-2]) feature['Day_2_Return'] = np.log(close[-2] / close[-3]) feature['Day_3_Return'] = np.log(close[-3] / close[-4]) feature['Weekly_Return'] = np.log(price / close[-DAYS_IN_A_WEEK]) feature['Monthly_Return'] = np.log(price / close[-DAYS_IN_A_MONTH]) feature['Quarterly_Return'] = np.log(price / close[-DAYS_IN_A_QUARTER]) feature['From_Weekly_High'] = np.log(price / np.max(close[-DAYS_IN_A_WEEK:])) feature['From_Weekly_Low'] = np.log(price / np.min(close[-DAYS_IN_A_WEEK:])) # Technical indicators pd_close = pd.Series(close) feature['RSI'] = momentum.rsi(pd_close).values[-1] feature['MACD_Rate'] = trend.macd_diff(pd_close).values[-1] / price feature['TSI'] = momentum.tsi(pd_close).values[-1] # Markets feature['VIX'] = vix # Other numerical factors # Fit five data points to a second order polynomial feature['Acceleration'] = (2 * close[-5] - 1 * close[-4] - 2 * close[-3] - 1 * close[-2] + 2 * close[-1]) / 14 feature['Momentum'] = (-2 * close[-5] - 1 * close[-4] + 1 * close[-2] + 2 * close[-1]) / 10 quarterly_returns = [ np.log(close[i] / close[i - 1]) for i in range(-DAYS_IN_A_QUARTER, -1) ] monthly_returns = quarterly_returns[-DAYS_IN_A_MONTH:] weekly_returns = quarterly_returns[-DAYS_IN_A_WEEK:] feature['Monthly_Skewness'] = stats.skew(monthly_returns) feature['Monthly_Volatility'] = np.std(monthly_returns) feature['Weekly_Skewness'] = stats.skew(weekly_returns) feature['Weekly_Volatility'] = np.std(weekly_returns) feature['Z_Score'] = ( feature['Day_1_Return'] - np.mean(quarterly_returns)) / np.std(quarterly_returns) feature['Monthly_Avg_Dollar_Volume'] = np.average( np.multiply(close[-DAYS_IN_A_MONTH - 1:-1], volume[-DAYS_IN_A_MONTH:])) / 1E6 return feature