def create_bollinger_bands(prices): bollUPPER, bollMIDDLE, bollLOWER = BBANDS(prices, timeperiod=20, nbdevup=2., nbdevdn=2., matype=0) upper_bolling_percent = np.reshape(bollUPPER / prices, (len(prices), 1)) lower_bolling_percent = np.reshape(bollLOWER / prices, (len(prices), 1)) bollinger_bands = np.hstack((upper_bolling_percent, lower_bolling_percent)) for time_period in range(10, 31): for up in range(18, 23): for down in range(18, 23): upper, middle, lower = BBANDS(prices, timeperiod=time_period, nbdevup=float(up) / 10, nbdevdn=float(down) / 10, matype=0) bollinger_bands = np.hstack( (bollinger_bands, np.reshape(upper / prices, (len(prices), 1)), np.reshape(lower / prices, (len(prices), 1)))) return bollinger_bands
def minwidth_BBANDS(p, ma_ts, sigma, mid_width): """ Custom technical indicator: Bollinger bands, with a user-defined minimum width. """ from talib import BBANDS import numpy as np # Obtain indicators (t_b, m_o, b_b) = BBANDS(p.values, timeperiod=ma_ts, nbdevup=sigma, nbdevdn=sigma) # Impose a minimum width on the bollinger bands - can't use nan values as clips t_m = np.isfinite( t_b * m_o) # top band mask: neither top band nor moving av can be nan b_m = np.isfinite( b_b * m_o) # bot band mask: neither bot band nor moving av can be nan # Clip bands t_b[t_m] = np.clip(t_b[t_m], m_o[t_m] + mid_width, np.inf) b_b[b_m] = np.clip(b_b[b_m], -np.inf, m_o[b_m] - mid_width) return t_b, m_o, b_b
def analyze(self, historical_data, signal=['close'], hot_thresh=None, cold_thresh=None, period_count=20, std_dev=2): """Check when close price cross the Upper/Lower bands. Args: historical_data (list): A matrix of historical OHCLV data. period_count (int, optional): Defaults to 20. The number of data points to consider for the BB bands indicator. signal (list, optional): Defaults to close. Unused in this indicator std_dev (int, optional): number of std dev to use. Common values are 2 or 1 Returns: pandas.DataFrame: A dataframe containing the indicator and hot/cold values. """ dataframe = self.convert_to_dataframe(historical_data) #Required to avoid getting same values for low, middle, up dataframe['close_10k'] = dataframe['close'] * 10000 up_band, mid_band, low_band = BBANDS(dataframe['close_10k'], timeperiod=period_count, nbdevup=std_dev, nbdevdn=std_dev, matype=0) bollinger = pandas.concat([dataframe, up_band, mid_band, low_band], axis=1) bollinger.rename(columns={ 0: 'up_band', 1: 'mid_band', 2: 'low_band' }, inplace=True) old_up, old_low = bollinger.iloc[-2]['up_band'], bollinger.iloc[-2][ 'low_band'] cur_up, cur_low = bollinger.iloc[-1]['up_band'], bollinger.iloc[-1][ 'low_band'] old_close = bollinger.iloc[-2]['close_10k'] cur_close = bollinger.iloc[-1]['close_10k'] bollinger['is_hot'] = False bollinger['is_cold'] = False bollinger['is_hot'].iloc[ -1] = old_low < old_close and cur_low > cur_close bollinger['is_cold'].iloc[ -1] = old_up > old_close and cur_up < cur_close bollinger['up_band'] = bollinger['up_band'] / 10000 bollinger['mid_band'] = bollinger['mid_band'] / 10000 bollinger['low_band'] = bollinger['low_band'] / 10000 return bollinger
def WADDAH_ATTAR_EXPLOSION(close, high, low, sensitive = 150, fast_period=20, slow_period = 40, channel_period = 20, channel_mult = 2, dead_zone=30): from talib import MACD from talib import BBANDS from talib import ATR from talib import WMA macd, macdsignal, macdhist = MACD(close, fastperiod=fast_period, slowperiod=slow_period, signalperiod=9) upperband, middleband, lowerband = BBANDS(close, timeperiod=channel_period, nbdevup=channel_mult, nbdevdn=channel_mult, matype=0) ind_trend1 = np.full(len(close), np.nan) ind_itrend1 = np.full(len(close), np.nan) ind_explo1 = np.full(len(close), np.nan) tr = WMA(ATR(high, low, close, 20),3) ind_dead = tr*dead_zone / 10 for i in range(0,len(close)): if(i<2): continue trend1 = (macd[i] - macd[i-1]) * sensitive; trend2 = (macd[i-1] - macd[i-2]) * sensitive; explo1 = (upperband[i] - lowerband[i]) #explo2 = (upperband[i-1] - lowerband[i-1]) if(trend1>=0): ind_trend1[i]=trend1 ind_itrend1[i]=0 if(trend1<0): ind_trend1[i]=0 ind_itrend1[i]=(trend1*-1) ind_explo1[i] = explo1 #print(str(i)+"\t "+str(close[i])+"\t "+str(close[i])+"\t "+str(ind_trend1[i])+"\t"+str(ind_itrend1[i])) return ind_trend1, ind_itrend1, ind_explo1, ind_dead
def refit(self, ohlcv, params=None, ba=None, **kwargs): """ refit the strategy using given parameters and return signals :param ohlcv: a DataFrame object with OHLCV columns ordered by date, ascending :param params: optimal parameters :ba: bid ask spread :return: signal """ required_params = ['trailing_window', 'ema_s', 'ema_l', 'bb'] if not all(param in params for param in required_params): raise KeyError("incorrect parameters") lookback = params['trailing_window'] close = ohlcv['close'] ema_s = EMA(close[-lookback:], timeperiod=params['ema_s']) ema_l = EMA(close[-lookback:], timeperiod=params['ema_l']) bb = BBANDS(close[-lookback:], timeperiod=params['bb']) if ba in None: buy_signal = (ema_s > ema_l) and (close[-1] > (bb[1])) and (close[-1] > ema_s) else: bid = ba['bid'] ask = ba['ask'] mid = (bid[-1] + ask[-1]) / 2 buy_signal = (ema_s > ema_l) and (mid > (bb[1])) and (mid > ema_s) return {'buy': buy_signal, 'sell': None}
def bbp(price): up, mid, low = BBANDS(close, timeperiod=200, nbdevup=2, nbdevdn=2, matype=0) bbp = (price['AdjClose'] - low) / (up - low) return bbp
def add_technicals(price, close): price["RSI"] = RSI(close, timeperiod=14) price["BBP"] = bbp(price) price["BB_up"], price["BB_mid"], price["BB_low"] = BBANDS(close, timeperiod=20, nbdevup=2, nbdevdn=2, matype=0) return price
def process_data(self, data): r = None try: r = BBANDS(np.array(data['close']), timeperiod=self.period, nbdevup=self.nbdevup, nbdevdn=self.nbdevdn, matype=self.matype) except Exception as e: print("Exception in BollingerBands", e) logger.exception(e) r = {self.k: [0,0]} self.setd(0 if np.isnan(r[self.k][-1]) else r[self.k][-1]) return self
def bbp(): up, mid, low = BBANDS(close, timeperiod=20, nbdevup=2.5, nbdevdn=2.5, matype=8) # up, mid, low = BBANDS(close, timeperiod=20, nbdevup=2, nbdevdn=2, matype=0) # bbp = (price['Close'] - low) / (up - low) bbp = (close - low) / (up - low) return bbp, up, mid, low
async def calc_pullback(self) -> None: for i, row in self.portfolio.iterrows(): # print(row.symbol, len(self.data_bars[row.symbol])) bband = BBANDS( self.data_bars[row.symbol].close, timeperiod=7, nbdevdn=1, nbdevup=1, matype=MA_Type.EMA, ) lower_band = bband[2] upper_band = bband[0] volatility = upper_band[-1] - lower_band[-1] position = 0 profit = 0.0 count = 0 for i in range(-self.pullback_days, -1, 1): if (not position and self.data_bars[row.symbol].close[i - 1] < lower_band[i - 1] and self.data_bars[row.symbol].close[i] > self.data_bars[row.symbol].close[i - 1] and self.data_bars[row.symbol].close[i] > lower_band[i]): position = (self.portfolio_size // self.data_bars[row.symbol].open[i]) profit -= position * self.data_bars[row.symbol].open[i] count += 1 elif (position and self.data_bars[row.symbol].open[i] > upper_band[i - 1]): profit += position * self.data_bars[row.symbol].open[i] position = 0 self.portfolio.loc[self.portfolio.symbol == row.symbol, "count"] = count self.portfolio.loc[self.portfolio.symbol == row.symbol, "profit"] = profit self.portfolio.loc[self.portfolio.symbol == row.symbol, "volatility"] = volatility qty = int(count * self.risk_factor / volatility) self.portfolio.loc[self.portfolio.symbol == row.symbol, "qty"] = qty self.portfolio.loc[self.portfolio.symbol == row.symbol, "est"] = (qty * self.data_bars[row.symbol].close[-1]) self.portfolio.loc[ self.portfolio.symbol == row.symbol, "opt"] = bool( self.data_bars[row.symbol].close[-1] < lower_band[-1]) self.portfolio = self.portfolio.loc[(self.portfolio.profit > 0) & (self.portfolio.opt == True) & (self.portfolio.volatility > 2.0) & (self.portfolio.score > 35.0)]
def init(self): super().init() up_band, mid, down_band = BBANDS(self.data.Close, timeperiod=self.ma_len, nbdevup=self.band_width, nbdevdn=self.band_width, matype=0) self.up_band = self.I(lambda x: up_band, 'up_band') self.mid = self.I(lambda x: mid, 'mid') self.down_band = self.I(lambda x: down_band, 'down_band')
def get_bbands_score(self, product_df): upper_df, middle_df, lower_df = BBANDS(product_df.close, 20, 2, 2) close = product_df.close.iloc[-1] upper = upper_df.iloc[-1] middle = middle_df.iloc[-1] lower = lower_df.iloc[-1] #print(f"Upper: {upper}, Middle: {middle}, Lower: {lower}") if close < lower: return 1 elif close > upper: return -1 else: return 0
def analyze(self, historical_data, signal=['bbp'], hot_thresh=0, cold_thresh=0.8, period_count=20, std_dev=2): """Check when close price cross the Upper/Lower bands. Args: historical_data (list): A matrix of historical OHCLV data. period_count (int, optional): Defaults to 20. The number of data points to consider for the BB bands indicator. signal (list, optional): Defaults bbp value. hot_thresh (float, optional): Defaults to 0. The threshold at which this might be good to purchase. cold_thresh (float, optional): Defaults to 0.8. The threshold at which this might be good to sell. std_dev (int, optional): number of std dev to use. Common values are 2 or 1 Returns: pandas.DataFrame: A dataframe containing the indicator and hot/cold values. """ dataframe = self.convert_to_dataframe(historical_data) mfi = abstract.MFI(dataframe, period_count=14) # Required to avoid getting same values for low, middle, up dataframe['close_10k'] = dataframe['close'] * 10000 up_band, mid_band, low_band = BBANDS(dataframe['close_10k'], timeperiod=period_count, nbdevup=std_dev, nbdevdn=std_dev, matype=0) bbp = (dataframe['close_10k'] - low_band) / (up_band - low_band) bollinger = pandas.concat([dataframe, bbp, mfi], axis=1) bollinger.rename(columns={0: 'bbp', 1: 'mfi'}, inplace=True) bollinger['is_hot'] = False bollinger['is_cold'] = False bollinger['is_hot'].iloc[ -1] = bollinger['bbp'].iloc[-2] <= hot_thresh and bollinger[ 'bbp'].iloc[-2] < bollinger['bbp'].iloc[-1] bollinger['is_cold'].iloc[ -1] = bollinger['bbp'].iloc[-1] >= cold_thresh return bollinger
def get_indicators(df, indicators=[]): if "bbands" in indicators: df["upperband"], df["middleband"], df["lowerband"] = BBANDS( df["close"], timeperiod=20, nbdevup=2, nbdevdn=2, matype=0) if "macd" in indicators: df["macd"], df["macdsignal"], df["macdhist"] = MACD(df["close"], fastperiod=12, slowperiod=26, signalperiod=9) if "price_logreturn" in indicators: df["price_logreturn"] = log_return(df["close"].to_numpy()) if "volume_logreturn" in indicators: df["volume_logreturn"] = log_return(df["volume"].to_numpy()) return df
def bbww(price): multiplier = 1000000 # Bollinger Band Width = (Upper Band - Lower Band) / Simple Moving Average for the same period. up, mid, low = BBANDS(price['Close'].values * multiplier, timeperiod=5, nbdevup=2, nbdevdn=2, matype=talib.MA_Type.T3) # up, mid, low = up * 10000000, mid * 10000000, low * 10000000 sma = SMA(price['Close'].values, timeperiod=14) * multiplier bbw = (up - low) / (sma) return bbw
def get_technical_analysis(stock_data: pd.DataFrame, stock_name: str) -> pd.DataFrame: data = stock_data.query(f'stock_name=="{stock_name}"') close_prices = data['Adj Close'].values up, mid, low = BBANDS(close_prices, timeperiod=20, nbdevup=2, nbdevdn=2, matype=0) rsi = RSI(close_prices, timeperiod=14) bbp = (data['Adj Close'] - low) / (up - low) data['lower_bound'] = low data['upper_bound'] = up data['RSI'] = rsi data['BBP'] = bbp return data
async def handle_sell_side( self, symbols_position: Dict[str, float], data_loader: DataLoader, now: datetime, trade_fee_precentage: float, ) -> Dict[str, Dict]: actions = {} for symbol, position in symbols_position.items(): if position == 0: continue current_price = data_loader[symbol].close[now] resampled_close = self.calc_close(symbol, data_loader, now) bband = BBANDS( resampled_close, timeperiod=7, nbdevdn=1, nbdevup=1, matype=MA_Type.EMA, ) yesterday_upper_band = bband[0][-2] print( f"\ncurrent_price > yesterday_upper_band : {current_price > yesterday_upper_band}({current_price} < {yesterday_upper_band})" ) if current_price > yesterday_upper_band: sell_indicators[symbol] = { "upper_band": bband[0][-2:].tolist(), "lower_band": bband[2][-2:].tolist(), } tlog( f"[{self.name}][{now}] Submitting sell for {position} shares of {symbol} at market" ) tlog(f"indicators:{sell_indicators[symbol]}") actions[symbol] = { "side": "sell", "qty": str(position), "type": "limit", "limit_price": str(current_price), } return actions
def bbp(price): # bolinger bands % multiplier = 1000000 up, mid, low = BBANDS(price['Close'].values * multiplier, timeperiod=5, nbdevup=2, nbdevdn=2, matype=talib.MA_Type.T3) # multiply to avoid very small numbers leading to inf # up, mid, low = up * mutiplier, mid * mutiplier, low * mutiplier bbp = (((price['Close'] * multiplier) - low) / (up - low)) if isNaN(bbp.values[-1]): print("ok") return bbp
def handle_data(context, data): required_params = ['trailing_window', 'ema_s', 'ema_l', 'bb'] if not all(param in context.params for param in required_params): raise KeyError("incorrect parameter list") trailing_window = data.history( context.asset, 'close', context.params['trailing_window'], '1d') if trailing_window.isnull().values.any(): return ema_s = EMA(trailing_window.values, timeperiod=context.params['ema_s']) ema_l = EMA(trailing_window.values, timeperiod=context.params['ema_l']) bb = BBANDS(trailing_window.values, timeperiod=context.params['bb']) buy = False sell = False buy_signal = (ema_s[-1] > ema_l[-1]) and ( trailing_window.values[-1] > (bb[1][-1])) and (trailing_window.values[-1] > ema_s[-1]) if buy_signal and not context.invested: order(context.asset, 100) context.invested = True buy = True elif not buy_signal and context.invested: order(context.asset, -100) context.invested = False sell = True record(BTC=data.current(context.asset, "price"), ema_s=ema_s[-1], ema_l=ema_l[-1], bb=bb[1][-1], buy=buy, sell=sell)
def create_bollinger_bands(historical_data): prices = historical_data['Adj Close'].as_matrix() bollinger_bands = dict() for time_period in range(10, 31): for up in range(18, 23): for down in range(18, 23): upper, middle, lower = BBANDS(prices, timeperiod=time_period, nbdevup=float(up) / 10, nbdevdn=float(down) / 10, matype=0) bollinger_bands['bbands_upper_{}_{}_{}'.format( time_period, up, down)] = upper / prices bollinger_bands['bbands_lower_{}_{}_{}'.format( time_period, up, down)] = lower / prices macds_dataframe = pd.DataFrame(bollinger_bands) return historical_data.join(macds_dataframe)
def _calc_indicator(self, OHLCV_input): """ Calculates the Bollinger bands technical indicator using a wrapper for the TA-lib Args: :param OHLCV_input: the dataframe with the Open, High, Low, Close and Volume values :type OHLCV_input: pandas DataFrame Returns: DataFrame with scaled features with size (n_observations, n_features). """ try: close = OHLCV_input['close'].values[:, 0] except IndexError: close = OHLCV_input['close'].values upperband, middleband, lowerband = BBANDS(close, self.__timeperiod, self.__nbdevup, self.__nbdevdn, self.__matype) upperband = DataFrame(upperband) middleband = DataFrame(middleband) lowerband = DataFrame(lowerband) return concat([upperband, middleband, lowerband], axis=1, ignore_index=True)
def main(): file_content = file_io_service.load_historical_data('PETR4.SA') file_content = file_content.dropna() close = file_content['Adj Close'].values date = np.array( list( map(lambda x: date_helper.parse_date_to_datetime(x), file_content['Date']))) rsi = RSI(close, timeperiod=14) macd, macdsignal, macdhist = MACD(close, fastperiod=12, slowperiod=26, signalperiod=9) up, mid, low = BBANDS(close, timeperiod=20, nbdevup=2, nbdevdn=2, matype=0) fig, (ax0, ax1, ax2) = plt.subplots(3, 1, sharex=True, figsize=(12, 8)) ax0.plot(date, close, label='Close') ax0.set_xlabel('Date') ax0.set_ylabel('Close') ax0.grid() ax1.plot(date, rsi, label='Close', linewidth=.5) ax1.set_xlabel('Date') ax1.set_ylabel('Close') ax1.grid() ax2.plot(date, up, label='BB_up', color='BLUE', linewidth=.5) ax2.plot(date, close, label='AdjClose', color='BLACK', linewidth=.5) ax2.plot(date, low, label='BB_low', color='RED', linewidth=.5) ax2.fill_between(date, y1=low, y2=up, color='#adccff', alpha='0.3') ax2.set_xlabel('Date') ax2.set_ylabel('Bollinger Bands') ax2.grid() fig.tight_layout() plt.show()
def compute_bb(close): high, mid, low = BBANDS(close, timeperiod=20) return pd.DataFrame({'bb_high': high, 'bb_low': low}, index=close.index)
def bbands200(self, df, pattern, patterntype): df = df.dropna() #1. Calculate ATR for potential trade atr = atrcalc.ATRcalc(df) ##b. get BBands bband = df.head(21) bband = bband.iloc[1:] bband = bband.iloc[::-1] bbandInput = bband['close'].values upperband, middleband, lowerband = BBANDS(bbandInput, timeperiod=20, nbdevup=2, nbdevdn=2, matype=0) ##c. 200EMA emaInput = df.head(200) emaInput = emaInput.iloc[::-1] EMAclose = emaInput['close'].values ema = EMA(EMAclose, timeperiod=200) ##d. current price action priceaction = df.head(1) pricehigh = priceaction['high'].values[0] pricelow = priceaction['low'].values[0] priceclose = priceaction['close'].values[0] if pricehigh > upperband[-1]: breakBand = -1 elif pricelow < lowerband[-1]: breakBand = 1 else: breakBand = 0 if pricelow > ema[-1]: marketEMA = 1 elif pricehigh < ema[-1]: marketEMA = -1 else: marketEMA = 0 ##OUTPUT if marketEMA == 1 and pattern > 0 and patterntype == -1 and breakBand == 1: position = 1 elif marketEMA == -1 and pattern < 0 and patterntype == -1 and breakBand == -1: position = -1 else: position = 0 amount = 50 if position == 1: stoploss = priceclose - 1.05 * atr takeprofit = priceclose + 1.45 * atr # amount = priceclose / (priceclose - stoploss) if (stoploss - priceclose) * amount < 0.1: position = 0 amount = 0 stoploss = 0 takeprofit = 0 elif position == -1: stoploss = priceclose + 1.05 * atr takeprofit = priceclose - 1.45 * atr # amount = priceclose / (stoploss - priceclose) if (stoploss - priceclose) * amount < 0.1: position = 0 amount = 0 stoploss = 0 takeprofit = 0 else: stoploss = 0 takeprofit = 0 amount = 0 if position * pattern > 0: confidence = abs(pattern) elif position * pattern < 0: confidence = abs(1 / pattern) elif position == 0: confidence = 0 else: confidence = 1 # ##FOR TEST # position = 1 return [position, amount, priceclose, stoploss, takeprofit, confidence]
def bbp(data): price = data.dropna() close = price['Close'].values up, mid, low = BBANDS(close, timeperiod=20, nbdevup=2, nbdevdn=2, matype=0) bbp = (price['Close'] - low) / (up - low) return bbp
import pandas as pd pd.core.common.is_list_like = pd.api.types.is_list_like import pandas_datareader.data as web import matplotlib.pyplot as plt from talib import RSI, BBANDS import datetime as dt import numpy as np start = '2015-04-22' end = '2017-04-22' symbol = 'MCD' max_holding = 100 price = web.DataReader(name=symbol, data_source='quandl', start=start, end=end) print(price.head()) price = price.iloc[::-1] print(price.head()) price = price.dropna() close = price['AdjClose'].values up, mid, low = BBANDS(close, timeperiod=20, nbdevup=2, nbdevdn=2, matype=0) rsi = RSI(close, timeperiod=14) print("RSI (first 10 elements)\n", rsi[14:24])
def bbands(close, length=None, std=None, mamode=None, ddof=0, offset=None, **kwargs): """Indicator: Bollinger Bands (BBANDS)""" # Validate arguments length = int(length) if length and length > 0 else 5 std = float(std) if std and std > 0 else 2.0 mamode = mamode if isinstance(mamode, str) else "sma" ddof = int(ddof) if ddof >= 0 and ddof < length else 1 close = verify_series(close, length) offset = get_offset(offset) if close is None: return # Calculate Result if Imports["talib"]: from talib import BBANDS upper, mid, lower = BBANDS(close, length) else: standard_deviation = stdev(close=close, length=length, ddof=ddof) deviations = std * standard_deviation # deviations = std * standard_deviation.loc[standard_deviation.first_valid_index():,] mid = ma(mamode, close, length=length, **kwargs) lower = mid - deviations upper = mid + deviations ulr = non_zero_range(upper, lower) bandwidth = 100 * ulr / mid percent = non_zero_range(close, lower) / ulr # Offset if offset != 0: lower = lower.shift(offset) mid = mid.shift(offset) upper = upper.shift(offset) bandwidth = bandwidth.shift(offset) percent = bandwidth.shift(offset) # Handle fills if "fillna" in kwargs: lower.fillna(kwargs["fillna"], inplace=True) mid.fillna(kwargs["fillna"], inplace=True) upper.fillna(kwargs["fillna"], inplace=True) bandwidth.fillna(kwargs["fillna"], inplace=True) percent.fillna(kwargs["fillna"], inplace=True) if "fill_method" in kwargs: lower.fillna(method=kwargs["fill_method"], inplace=True) mid.fillna(method=kwargs["fill_method"], inplace=True) upper.fillna(method=kwargs["fill_method"], inplace=True) bandwidth.fillna(method=kwargs["fill_method"], inplace=True) percent.fillna(method=kwargs["fill_method"], inplace=True) # Name and Categorize it lower.name = f"BBL_{length}_{std}" mid.name = f"BBM_{length}_{std}" upper.name = f"BBU_{length}_{std}" bandwidth.name = f"BBB_{length}_{std}" percent.name = f"BBP_{length}_{std}" upper.category = lower.category = "volatility" mid.category = bandwidth.category = upper.category # Prepare DataFrame to return data = { lower.name: lower, mid.name: mid, upper.name: upper, bandwidth.name: bandwidth, percent.name: percent } bbandsdf = DataFrame(data) bbandsdf.name = f"BBANDS_{length}_{std}" bbandsdf.category = mid.category return bbandsdf
def runModel(factors, paras): import pandas as pd from talib import MACD, SMA, LINEARREG_SLOPE, RSI, BBANDS, KAMA import numpy as np import matplotlib.pyplot as plt from keras.models import Sequential from keras.layers import Dense, Activation, LSTM from keras.optimizers import SGD, RMSprop, Adagrad, Adam, Adamax, Nadam from keras.callbacks import EarlyStopping close = data['adjclose'] date = list(data['date']) ret = close.diff() / close.shift(1) #2: rise, 1:stay, 0:drop ret_dir = 1 * (ret > ret.quantile(0.66)) + 1 * (ret > ret.quantile(0.33)) #ret_dir=ret>ret.quantile(0.6) MA_diff1 = SMA(close, timeperiod=5) - close MA_diff2 = SMA(close, timeperiod=5) - SMA(close, timeperiod=15) macd, macdsignal, macdhist = MACD(close, fastperiod=12, slowperiod=26, signalperiod=9) SLOPE5 = LINEARREG_SLOPE(close, timeperiod=5) SLOPE15 = LINEARREG_SLOPE(close, timeperiod=15) SLOPE_diff = LINEARREG_SLOPE(close, timeperiod=5) - LINEARREG_SLOPE( close, timeperiod=10) SKEW = ret.rolling(window=10, center=False).skew() RSI20 = RSI(close, timeperiod=20) RSI_SIG = 1 * (RSI20 < 40) - (RSI20 > 60) upper, middle, lower = BBANDS(close, timeperiod=15) BOLL_SIG = 1 * (close < lower) - (close > upper) MACD_RATIO = macd / SMA(macd, timeperiod=5) Kalman = KAMA(close, timeperiod=5) STD = close.rolling(window=10, center=False).std() KALMAN_SIG = 1 * (close < Kalman - 0.1 * STD) - (close > Kalman + 0.1 * STD) train_ratio = paras[0] trans_fee = paras[1] stop_loss = paras[2] take_profit = paras[3] originalDataSet = pd.DataFrame({ 'dir': ret_dir.shift(-1), 0: MA_diff1, 1: MA_diff2, 2: macd, 3: SLOPE5, 4: SLOPE15, 5: SLOPE_diff, 6: SKEW, 7: RSI20, 8: RSI_SIG, 9: BOLL_SIG, 10: KALMAN_SIG, 11: MACD_RATIO }) originalDataSet = originalDataSet.dropna(axis=0) del_num = [] for i in range(len(factors)): if factors[i] == 0: del_num.append(i) originalDataSet = originalDataSet.drop(labels=del_num, axis=1) def normalize(train, flag=0): if flag == 0: train_norm = train.apply(lambda x: (x - np.mean(x)) / (np.max(x) - np.min(x))) else: y = train.iloc[:, 0] train_norm = train.apply(lambda x: (x - np.mean(x)) / (np.max(x) - np.min(x))) train_norm.iloc[:, 0] = y return train_norm win_size = 5 def windows(da, window_size): start = 0 while start < len(da): yield start, start + window_size start += 1 # start += (window_size // 2) def extract_segments(da, window_size=30): segments = np.empty((0, (window_size) * (da.shape[1] - 1))) labels = np.empty((0)) for (start, end) in windows(da, window_size): if end >= len(originalDataSet): break if (len(da.iloc[start:end]) == (window_size)): signal = np.array(da.iloc[start:end, 1:]).reshape(1, -1)[0] segments = np.vstack([segments, signal]) labels = np.append(labels, da.iloc[end, 0]) return segments, labels segments, labels = extract_segments(originalDataSet, win_size) num_train = int(train_ratio * labels.shape[0]) num_test = labels.shape[0] - num_train dummy_labels = np.asarray(pd.get_dummies(labels), dtype=np.int8) reshaped_segments = segments.reshape( [labels.shape[0], win_size, originalDataSet.shape[1] - 1]) train_x = reshaped_segments[:num_train] train_y = dummy_labels[:num_train] test_x = reshaped_segments[num_train:] test_y = dummy_labels[num_train:] batch_size = 32 model = Sequential() model.add( LSTM(units=50, return_sequences=True, input_shape=[train_x.shape[1], train_x.shape[2]], dropout=0.2)) model.add(Activation('relu')) model.add( LSTM(units=50, return_sequences=True, input_shape=[train_x.shape[1], train_x.shape[2]], dropout=0.2)) model.add(Activation('relu')) model.add(LSTM(units=24, dropout=0.2, recurrent_dropout=0.2)) model.add(Activation('relu')) model.add(Dense(3, activation='softmax')) sgd = SGD(lr=0.002, decay=1e-6, momentum=0.9, nesterov=True) rmsprop = RMSprop(lr=0.0002, rho=0.9, epsilon=1e-06) adagrad = Adagrad(lr=0.001, epsilon=1e-06) adam = Adam(lr=0.002, beta_1=0.9, beta_2=0.999, epsilon=1e-08) adamax = Adamax(lr=0.002, beta_1=0.9, beta_2=0.999, epsilon=1e-08) nadam = Nadam(lr=0.0005, beta_1=0.9, beta_2=0.999, epsilon=1e-08, schedule_decay=0.004) model.compile(loss='categorical_crossentropy', optimizer=sgd, metrics=['accuracy']) model.fit(train_x, train_y, epochs=50, batch_size=batch_size, validation_data=(test_x, test_y), verbose=2, shuffle=False, callbacks=[EarlyStopping(patience=40)]) initial_captial = 10000000 pred_y = model.predict(test_x) norm_y = np.diff(np.log(pred_y), axis=0) norm_y = np.array(norm_y, dtype=float) price = list(close[len(close) - 1 - len(pred_y):len(close) - 1]) signal = [0 for i in range(len(pred_y))] buySell = [0 for i in range(len(pred_y))] buySell_size = [0 for i in range(len(pred_y))] position = [0 for i in range(len(pred_y))] Notional = [0 for i in range(len(pred_y))] CumNotional = [0 for i in range(len(pred_y))] PnL = [0 for i in range(len(pred_y))] cost = 1 station = 0 for i in range(1, len(pred_y)): temp = list(norm_y[i - 1]) signal[i] = temp.index(max(temp)) - 1 if i == 0: buySell[i] = signal[i] buySell_size[i] = (initial_captial + PnL[-1]) // price[i] * buySell[i] position[i] = buySell_size[i] Notional[i] = -buySell_size[i] * price[i] CumNotional[i] = Notional[i] PnL[i] = CumNotional[i] + position[i] * price[i] else: station = np.sign(position[i - 1]) if signal[i] != station: if station == 1: if signal[i] == 0: buySell_size[i] = -position[i - 1] if signal[i] == -1: buySell_size[i] = -position[i - 1] - ( initial_captial + PnL[-1]) // price[i] elif station == 0: if signal[i] == 1: buySell_size[i] = (initial_captial + PnL[-1]) // price[i] if signal[i] == -1: buySell_size[i] = -(initial_captial + PnL[-1]) // price[i] else: if signal[i] == 0: buySell_size[i] = -position[i - 1] if signal[i] == 1: buySell_size[i] = -position[i - 1] + ( initial_captial + PnL[-1]) // price[i] #stop loss and take profit if i != 0 and buySell_size[i] == 0 and position[i - 1] != 0: if position[i - 1] > 0: if price[i] / cost > 1 + take_profit or price[ i] / cost < 1 - stop_loss: buySell_size[i] = -position[i - 1] else: if price[i] / cost < 1 - take_profit or price[ i] / cost > 1 + stop_loss: buySell_size[i] = -position[i - 1] position[i] = position[i - 1] + buySell_size[i] Notional[i] = -buySell_size[i] * price[i] CumNotional[i] = CumNotional[i - 1] + Notional[i] PnL[i] = CumNotional[i] + position[i] * price[i] if buySell_size[i] != 0 and position[i] != 0: cost = price[i] oneMinPnL = np.diff(PnL) oneMinPnL[0] = 0 from math import sqrt Sharpe = oneMinPnL.mean() / oneMinPnL.std() * sqrt(252) pnl = list(PnL) price = [round(x, 2) for x in price] pnl = [round(x, 2) for x in pnl] date = date[len(close) - 1 - len(pred_y):len(close) - 1] srp = round(Sharpe, 2) totalrtn = round(PnL[-1] / initial_captial, 2) return date, pnl, price, srp, totalrtn
def PlotStockChart(shareCode, showChart=False): RSI_T = 10 MACD_FAST = 10 MACD_SLOW = 21 MACD_SIGNAL = 5 BBAND_PERIOD = 21 data = pd.read_json('D:\\Personal\\share\\data\\' + shareCode + '.txt') data['t'] = pd.to_datetime(data['t'], unit='s') data['date'] = data['t'].dt.date data.set_index(['date'], inplace=True, drop=False) df = data # First instance trace1 = { 'x': df.index, 'open': df.o, 'close': df.c, 'high': df.h, 'low': df.l, 'type': 'candlestick', 'name': shareCode, 'showlegend': False } rsi = RSI(df.c, timeperiod=10) macd, macdSignal, macdHist = MACD(df.c, MACD_FAST, MACD_SLOW, MACD_SIGNAL) upper, middle, lower = BBANDS(df.c, timeperiod=BBAND_PERIOD, nbdevup=2, nbdevdn=2) # Second instance - avg_30 trace2 = { 'x': df.index, 'y': rsi, 'type': 'scatter', 'mode': 'lines', 'line': { 'width': 1, 'color': 'blue' }, 'name': 'RSI' } rsiLower = { 'x': df.index, 'y': 30 * (rsi / rsi), 'type': 'scatter', 'line': { 'width': 1, 'color': 'red' }, 'name': 'RSI Lower' } rsiUpper = { 'x': df.index, 'y': 70 * (rsi / rsi), 'type': 'scatter', 'line': { 'width': 1, 'color': 'red' }, 'name': 'RSI Upper' } # MACD trace4 = { 'x': df.index, 'y': macd, 'type': 'scatter', 'mode': 'lines', 'line': { 'width': 1, 'color': 'blue' }, 'name': 'macd' } trace5 = {'x': df.index, 'y': macdHist, 'type': 'bar', 'name': 'macdHist'} trace6 = { 'x': df.index, 'y': macdSignal, 'type': 'scatter', 'mode': 'lines', 'line': { 'width': 1, 'color': 'red' }, 'name': 'macdSignal' } bbUpper = { 'x': df.index, 'y': upper, 'type': 'scatter', 'mode': 'lines', 'line': { 'width': 1, 'color': 'blue' }, 'name': 'BB Upper' } bbLower = { 'x': df.index, 'y': lower, 'type': 'scatter', 'mode': 'lines', 'line': { 'width': 1, 'color': 'blue' }, 'name': 'BB Lower' } bbMiddle = { 'x': df.index, 'y': middle, 'type': 'scatter', 'mode': 'lines', 'line': { 'width': 1, 'color': 'orange' }, 'name': 'BB Middle' } # Aggregate all instances and define 'data' variable xaxisType = {'type': "category", 'categoryorder': 'category ascending'} layout = dict(title=shareCode, xaxis=xaxisType, xaxis3=xaxisType, xaxis4=xaxisType) fig = make_subplots(rows=4, cols=1, shared_xaxes=True, vertical_spacing=0.02) fig.append_trace(trace1, row=1, col=1) fig.append_trace(bbLower, row=1, col=1) fig.append_trace(bbMiddle, row=1, col=1) fig.append_trace(bbUpper, row=1, col=1) fig.append_trace(trace2, row=4, col=1) fig.append_trace(rsiLower, row=4, col=1) fig.append_trace(rsiUpper, row=4, col=1) fig.append_trace(trace4, row=3, col=1) fig.append_trace(trace5, row=3, col=1) fig.append_trace(trace6, row=3, col=1) fig.update_layout(layout) def zoom(layout, xrange): in_view = df.loc[fig.layout.xaxis.range[0]:fig.layout.xaxis.range[1]] fig.layout.yaxis.range = [ in_view.High.min() - 10, in_view.High.max() + 10 ] #fig.layout.on_change(zoom, 'xaxis.range') fig.layout.on_change( lambda obj, xrange, yrange: print("%s-%s" % (xrange, yrange)), ('xaxis', 'range'), ('yaxis', 'range')) if showChart: fig.show() else: fig.write_html('D:\\Personal\\share\\results\\charts\\' + shareCode + '.html', include_plotlyjs='cdn') return #PlotStockChart('JKH.N0000', True)
def calculate_signals(self): for symbol in self.symbol_list: print('Searching for {1} signals ...'.format(symbol)) last_price = self.data_handler.current_price(symbol)[0] h1_highs = self.data_handler.get_latest_bars_values( symbol, 'high', timeframe='H1', N=self.bars_window) h1_lows = self.data_handler.get_latest_bars_values( symbol, 'low', timeframe='H1', N=self.bars_window) h1_closes = self.data_handler.get_latest_bars_values( symbol, 'close', timeframe='H1', N=self.bars_window) h1_hlc3 = (h1_highs + h1_lows + h1_closes) / 3 h1_ema_50 = EMA(h1_hlc3, timeperiod=50) h1_ema_100 = EMA(h1_hlc3, timeperiod=100) h1_ema_200 = EMA(h1_hlc3, timeperiod=200) m15_highs = self.data_handler.get_latest_bars_values( symbol, 'high', timeframe='m15', N=self.bars_window) m15_lows = self.data_handler.get_latest_bars_values( symbol, 'low', timeframe='m15', N=self.bars_window) m15_closes = self.data_handler.get_latest_bars_values( symbol, 'close', timeframe='m15', N=self.bars_window) m15_hlc3 = (m15_highs + m15_lows + m15_closes) / 3 m15_ema_50 = EMA(m15_hlc3, timeperiod=50) m15_ema_100 = EMA(m15_hlc3, timeperiod=100) m15_ema_200 = EMA(m15_hlc3, timeperiod=200) m15_price_bb_up, m15_price_bb_mid, m15_price_bb_low = BBANDS( m15_hlc3, timeperiod=20, nbdevup=2, nbdevdn=2) m15_price_bb_low_dist = (m15_price_bb_mid + m15_price_bb_low) / 2 m15_price_bb_up_dist = (m15_price_bb_up + m15_price_bb_mid) / 2 m15_rsi = RSI(m15_closes, timeperiod=14) m15_rsi_bb_up, m15_rsi_bb_mid, m15_rsi_bb_low = BBANDS( m15_rsi, timeperiod=20, nbdevup=2, nbdevdn=2) m15_stochrsi = STOCHRSI(pd.Series(m15_closes), timeperiod=14) m15_atr = ATR(m15_highs, m15_lows, m15_closes, timeperiod=14) datetime = self.data_handler.get_latest_bar_datetime(symbol)[0] direction = None status = None position = 'Not yet' print(datetime) if last_price > h1_ema_50[-1] and last_price > h1_ema_100[ -1] and last_price > h1_ema_200[-1]: print('Uprend detected') if last_price > m15_ema_50[-1] and last_price > m15_ema_100[ -1] and last_price > m15_ema_200[-1]: print('Uprend confirmed') direction = 'LONG' if m15_rsi[-1] < m15_rsi_bb_low[-1]: print('Reversal Detected') status = 'Reversal detected' if last_price < m15_price_bb_low_dist[-1]: print('Reversal confirmed') status = 'Reversal confirmed' if m15_stochrsi[-1] < 25: print('Go LONG') position = 'Go ahead' elif last_price < h1_ema_50[-1] and last_price < h1_ema_100[ -1] and last_price < h1_ema_200[-1]: print('Downrend detected') if last_price < m15_ema_50[-1] and last_price < m15_ema_100[ -1] and last_price < m15_ema_200[-1]: print('Downrend confirmed') direction = 'SHORT' if m15_rsi[-1] > m15_rsi_bb_up[-1]: print('Reversal Detected') status = 'Reversal detected' if last_price > m15_price_bb_up_dist[-1]: print('Reversal confirmed') status = 'Reversal confirmed' if m15_stochrsi[-1] > 75: print('Go SHORT') position = 'Go ahead' else: pass print(symbol, direction, status, position, datetime) if status is not None: self.telegram.send_text({ 'symbol': symbol, 'direction': direction, 'status': status, 'position': position, 'atr': np.around(m15_atr[-1], decimals=5), 'datetime': datetime })