def calc(df, period, ohlc=['open', 'high', 'low', 'close']): """ Function to compute Average True Range (ATR) Args : df : Pandas DataFrame which contains ['date', 'open', 'high', 'low', 'close', 'volume'] columns period : Integer indicates the period of computation in terms of number of candles ohlc: List defining OHLC Column names (default ['Open', 'High', 'Low', 'Close']) Returns : df : Pandas DataFrame with new columns added for True Range (TR) ATR (ATR_$period) """ atr = 'ATR_' + str(period) # Compute true range only if it is not computed and stored earlier in the df if not 'TR' in df.columns: df['h-l'] = df[ohlc[1]] - df[ohlc[2]] df['h-yc'] = abs(df[ohlc[1]] - df[ohlc[3]].shift()) df['l-yc'] = abs(df[ohlc[2]] - df[ohlc[3]].shift()) df['TR'] = df[['h-l', 'h-yc', 'l-yc']].max(axis=1) df.drop(['h-l', 'h-yc', 'l-yc'], inplace=True, axis=1) # Compute EMA of true range using ATR formula after ignoring first row EMA.calc(df, 'TR', atr, period, alpha=True) return df
def KDJ(N=9, M1=3, M2=3): """ KDJ 随机指标 """ RSV = (CLOSE - LLV(LOW, N)) / (HHV(HIGH, N) - LLV(LOW, N)) * 100 K = EMA(RSV, (M1 * 2 - 1)) D = EMA(K, (M2 * 2 - 1)) J = K * 3 - D * 2 return K, D, J
def MACD(SHORT=12, LONG=26, M=9): """ MACD 指数平滑移动平均线 DIF组成的线叫做MACD线 DEA组成的线叫做Signal线 最后用DIFF减DEA,得Histogram """ DIFF = EMA(CLOSE, SHORT) - EMA(CLOSE, LONG) DEA = EMA(DIFF, M) MACD = (DIFF - DEA) * 2 return DIFF, DEA, MACD
def ema_test(column_names): ema_dates = [0, 1, 2, 3, 4] ema_data = [5.3, 6.7, 7.9, 7.1, 5.2] ema_df = DataFrame(data={"Test": ema_data}, index=ema_dates) ema_df.index.name = "Date" ema = EMA(ema_df, 4, column_names) assert list(ema.result.values) == [6.75, 6.13]
def compute_data(token): global one_hour_rsi #enddate = datetime.datetime(2020, 5, 4, 15,30,0,0) enddate = datetime.datetime.today() startdate = enddate - datetime.timedelta(15) try: df = historical_data.get(kite, token, startdate, enddate, candlesize) df = EMA.calc(df, 'close', 'ema_5', 5) df = EMA.calc(df, 'close', 'ema_20', 20) df = MACD.calc(df) df = MFI.calc(df) df = VWAP.calc(df) rsi = historical_data.get(kite, token, startdate, enddate, "60minute") rsi = RSI.calc(rsi) one_hour_rsi = rsi.RSI_14.values[-2] except Exception as e: print("******* ERROR Computing Historical Data ********", token, e) return df
def calc(df, fastEMA=12, slowEMA=26, signal=9, base='close'): """ Function to compute Moving Average Convergence Divergence (MACD) Args : df : Pandas DataFrame which contains ['date', 'open', 'high', 'low', 'close', 'volume'] columns fastEMA : Integer indicates faster EMA slowEMA : Integer indicates slower EMA signal : Integer indicates the signal generator for MACD base : String indicating the column name from which the MACD needs to be computed from (Default Close) Returns : df : Pandas DataFrame with new columns added for Fast EMA (ema_$fastEMA) Slow EMA (ema_$slowEMA) MACD (macd_$fastEMA_$slowEMA_$signal) MACD Signal (signal_$fastEMA_$slowEMA_$signal) MACD Histogram (MACD (hist_$fastEMA_$slowEMA_$signal)) """ fE = "ema_" + str(fastEMA) sE = "ema_" + str(slowEMA) macd = "macd_" + str(fastEMA) + "_" + str(slowEMA) + "_" + str(signal) sig = "signal_" + str(fastEMA) + "_" + str(slowEMA) + "_" + str(signal) hist = "hist_" + str(fastEMA) + "_" + str(slowEMA) + "_" + str(signal) # Compute fast and slow EMA EMA.calc(df, base, fE, fastEMA) EMA.calc(df, base, sE, slowEMA) # Compute MACD df[macd] = np.where( np.logical_and(np.logical_not(df[fE] == 0), np.logical_not(df[sE] == 0)), df[fE] - df[sE], 0) # Compute MACD Signal EMA.calc(df, macd, sig, signal) # Compute MACD Histogram df[hist] = np.where( np.logical_and(np.logical_not(df[macd] == 0), np.logical_not(df[sig] == 0)), df[macd] - df[sig], 0) df.drop(['ema_12', 'ema_26'], inplace=True, axis=1) return df
# TDXSTEP112:STICKLINE(B>0 AND B-B1<0,19,20,2,0),COLORGREEN; # # {绿红,绿柱必须>=4才能认定有效} # VAR3:= REF(VAR2,1)<0 AND VAR2>0 AND COUNT(VAR2 < 0, 7) == 6; # {红绿转折点,红柱必须 >= 4才能认定转折有效} # VAR4:=REF(B-B1,1)>0 AND B-B1<0 AND COUNT(VAR2 > 0, 7) == 6; # DRAWICON(VAR3 AND REF(B,BARSLAST(VAR4)) - B > 30,120,1); # DRAWICON(VAR3 AND B-REF(B,REF(BARSLAST(VAR3),1) + 1) > 20 AND COUNT(VAR2<0,10)<9,120,1); feed = MysqlFeed('D') feed.addBarsFromCode(1, '2018-01-01', '2019-08-15') VARV = (2 * CLOSE + HIGH + LOW) / 4 VARU = LLV(LOW, 30) VARA1 = HHV(HIGH, 30) B = EMA((VARV - VARU) / (VARA1 - VARU) * 100, 8) B1 = EMA(B, 5) VAR2 = B - B1 # #红->绿 # GREEN = (B-B1 < 0) & (REF(B-B1, 1) > 0) # GREELAST = BARSLAST(GREEN) # #绿->红 # RED = (B-B1 > 0) & (REF(B-B1, 1) < 0) # REDLAST = BARSLAST(RED) VAR3 = (REF(VAR2, 1) < 0) & (VAR2 > 0) & (COUNT(VAR2 < 0, 7) == 6) VAR4 = (REF(VAR2, 1) > 0) & (VAR2 < 0) & (COUNT(VAR2 > 0, 7) == 6) BUY = VAR3 & (REF(B, BARSLAST(VAR4)) - B > 30) BUY2 = VAR3 & (B - REF(B,
def testPolicy(symbol="JPM", sd=dt.datetime(2008, 1, 1), ed=dt.datetime(2009, 12, 31), sv=100000): ############################ # # Loading Data # ############################ prices = get_data([symbol], pd.date_range(sd, ed), True) prices = prices.drop(['SPY'], axis=1) prices = prices.fillna(method='ffill') prices = prices.fillna(method='bfill') prices = prices / prices.ix[0, ] ############################ # # Indicators # ############################ SMA_20 = SMA(prices, symbol, 20) SMA_50 = SMA(prices, symbol, 50) EMA_20 = EMA(prices, symbol, 20) EMA_50 = EMA(prices, symbol, 50) [SMA_20, SMA_20_std, BB_upper_band, BB_lower_band, BB_value] = BollingerBands(prices, symbol, 20, 2) momentum_20 = Momentum(prices, symbol, 20) indicators_df = pd.DataFrame(index=prices.index, columns=[ 'JPM', 'SMA_20days', 'SMA_50days', 'EMA_20days', 'EMA_50days', 'BB_upper_band', 'BB_lower_band', 'Momentum_20days' ]) indicators_df['JPM'] = prices[symbol] indicators_df['SMA_20days'] = SMA_20 indicators_df['SMA_50days'] = SMA_50 indicators_df['EMA_20days'] = EMA_20 indicators_df['EMA_50days'] = EMA_50 indicators_df['BB_upper_band'] = BB_upper_band indicators_df['BB_lower_band'] = BB_lower_band indicators_df['Momentum_20days'] = momentum_20 indicators_df = indicators_df.fillna(method='bfill') #print indicators_df ############################ # # Signal # ############################ signal_df = pd.DataFrame(index=prices.index, columns=['SMA', 'BB', 'Momentum']) signal_df.loc[signal_df.index[0], 'SMA'] = 0 signal_df.loc[signal_df.index[0], 'BB'] = 0 signal_df.loc[signal_df.index[0], 'Momentum'] = 0 row_counter = 1 for i, row in indicators_df[1:].iterrows(): current_price = row['JPM'] current_SMA20 = row['SMA_20days'] current_SMA50 = row['SMA_50days'] current_EMA20 = row['EMA_20days'] current_EMA50 = row['EMA_50days'] current_BB_up = row['BB_upper_band'] current_BB_down = row['BB_lower_band'] current_momentum = row['Momentum_20days'] previous_price = indicators_df['JPM'][row_counter - 1] previous_SMA20 = indicators_df['SMA_20days'][row_counter - 1] previous_SMA50 = indicators_df['SMA_50days'][row_counter - 1] previous_EMA20 = indicators_df['EMA_20days'][row_counter - 1] previous_EMA50 = indicators_df['EMA_50days'][row_counter - 1] previous_BB_up = indicators_df['BB_upper_band'][row_counter - 1] previous_BB_down = indicators_df['BB_lower_band'][row_counter - 1] previous_momentum = indicators_df['Momentum_20days'][row_counter - 1] row_counter += 1 #print "Current: ", current_momentum #print "Previous: ", previous_momentum ############################ # # SMA # ############################ if (previous_SMA50 > previous_SMA20) and (current_SMA50 < current_SMA20): signal_df.loc[i, 'SMA'] = 1 elif (previous_SMA50 < previous_SMA20) and (current_SMA50 > current_SMA20): signal_df.loc[i, 'SMA'] = -1 else: signal_df.loc[i, 'SMA'] = 0 ############################ # # BB # ############################ if (previous_price < previous_BB_down) and (current_price > current_BB_down): signal_df.loc[i, 'BB'] = 1 elif (previous_price > previous_BB_up) and (current_price < current_BB_up): signal_df.loc[i, 'BB'] = -1 else: signal_df.loc[i, 'BB'] = 0 ############################ # # EMA # ############################ #if (previous_EMA50 > previous_EMA20) and (current_EMA50 < current_EMA20): # signal_df.loc[i, 'EMA'] = 1 #elif (previous_EMA50 < previous_EMA20) and (current_EMA50 > current_EMA20): # signal_df.loc[i, 'EMA'] = -1 #else: # signal_df.loc[i, 'EMA'] = 0 ############################ # # Momentum # ############################ if (previous_momentum < 0) and (current_momentum >= 0): signal_df.loc[i, 'Momentum'] = 1 elif (previous_momentum >= 0) and (current_momentum < 0): signal_df.loc[i, 'Momentum'] = -1 else: signal_df.loc[i, 'Momentum'] = 0 signal_df["SUM"] = signal_df.sum(axis=1) signal_df["Signal"] = signal_df["SUM"] signal_df.loc[signal_df["SUM"] <= -1, "Signal"] = -1 signal_df.loc[signal_df["SUM"] >= 1, "Signal"] = 1 signal_df.loc[signal_df["SUM"] == 0, "Signal"] = 0 #print signal_df.head(10) signal_df.to_csv("signal.csv") df_trades = pd.DataFrame(index=signal_df.index, columns=[symbol]) df_trades[symbol] = np.zeros(signal_df.shape[0]) holding = 0 indicators_df['Final_Signal'] = np.zeros(indicators_df.shape[0]) # Trading Scheme for i in df_trades.index: #print i if holding == 0: if signal_df.loc[i, "Signal"] == 1: df_trades.loc[i, symbol] = 1000 holding = 1000 indicators_df.loc[i, 'Final_Signal'] = 1 elif signal_df.loc[i, "Signal"] == -1: df_trades.loc[i, symbol] = -1000 holding = -1000 indicators_df.loc[i, 'Final_Signal'] = -1 else: df_trades.loc[i, symbol] = 0 elif holding == 1000: if signal_df.loc[i, "Signal"] == -1: df_trades.loc[i, symbol] = -2000 indicators_df.loc[i, 'Final_Signal'] = -1 holding = -1000 elif holding == -1000: if signal_df.loc[i, "Signal"] == 1: df_trades.loc[i, symbol] = 2000 indicators_df.loc[i, 'Final_Signal'] = 1 holding = 1000 df_trades.to_csv("trades.csv") return (df_trades, indicators_df)
def myTradingSystem( DATE, OPEN, HIGH, LOW, CLOSE, VOL, USA_ADP, USA_EARN, USA_HRS, USA_BOT, USA_BC, USA_BI, USA_CU, USA_CF, USA_CHJC, USA_CFNAI, USA_CP, USA_CCR, USA_CPI, USA_CCPI, USA_CINF, USA_DFMI, USA_DUR, USA_DURET, USA_EXPX, USA_EXVOL, USA_FRET, USA_FBI, USA_GBVL, USA_GPAY, USA_HI, USA_IMPX, USA_IMVOL, USA_IP, USA_IPMOM, USA_CPIC, USA_CPICM, USA_JBO, USA_LFPR, USA_LEI, USA_MPAY, USA_MP, USA_NAHB, USA_NLTTF, USA_NFIB, USA_NFP, USA_NMPMI, USA_NPP, USA_EMPST, USA_PHS, USA_PFED, USA_PP, USA_PPIC, USA_RSM, USA_RSY, USA_RSEA, USA_RFMI, USA_TVS, USA_UNR, USA_WINV, exposure, equity, settings): nMarkets = CLOSE.shape[1] lookback = settings['lookback'] pos = np.zeros(nMarkets) markets = settings['markets'] w = settings['market_factor_weights'] lweights, sweights = econ_long_short_allocation( markets, DATE[0], DATE[-1], w, activate=settings['dynamic_portfolio_allocation']) sentiment_data = settings['sentiment_data'] covid_data = settings['covid_data'] # to understand how this system works print("Using data from {} onwards to predict/take position in {}".format( DATE[0], DATE[-1])) OPEN = np.transpose(OPEN)[1:] HIGH = np.transpose(HIGH)[1:] LOW = np.transpose(LOW)[1:] CLOSE = np.transpose(CLOSE)[1:] VOL = np.transpose(VOL)[1:] if settings['model'] == 'TA': ''' Based on factors from https://www.investing.com/technical/us-spx-500-futures-technical-analysis ################ TREND FOLOWING ################ Simple Moving Average (SMA) crosses, period 5,10,20,50,100,200 ''' # indicators SMA5s = [SMA(close, 5) for close in CLOSE] SMA10s = [SMA(close, 10) for close in CLOSE] SMA20s = [SMA(close, 20) for close in CLOSE] SMA50s = [SMA(close, 50) for close in CLOSE] SMA100s = [SMA(close, 100) for close in CLOSE] SMA200s = [SMA(close, 200) for close in CLOSE] # signals def buy_condition(close, sma): return (close[-1] > sma[-1]) and (close[-2] <= sma[-2]) def sell_condition(close, sma): return (close[-1] < sma[-1]) and (close[-2] >= sma[-2]) SMA5_cross_buys = [ True if buy_condition(close, sma) else False for close, sma in zip(CLOSE, SMA5s) ] SMA5_cross_sells = [ True if sell_condition(close, sma) else False for close, sma in zip(CLOSE, SMA5s) ] SMA10_cross_buys = [ True if buy_condition(close, sma) else False for close, sma in zip(CLOSE, SMA10s) ] SMA10_cross_sells = [ True if sell_condition(close, sma) else False for close, sma in zip(CLOSE, SMA10s) ] SMA20_cross_buys = [ True if buy_condition(close, sma) else False for close, sma in zip(CLOSE, SMA20s) ] SMA20_cross_sells = [ True if sell_condition(close, sma) else False for close, sma in zip(CLOSE, SMA20s) ] SMA50_cross_buys = [ True if buy_condition(close, sma) else False for close, sma in zip(CLOSE, SMA50s) ] SMA50_cross_sells = [ True if sell_condition(close, sma) else False for close, sma in zip(CLOSE, SMA50s) ] SMA100_cross_buys = [ True if buy_condition(close, sma) else False for close, sma in zip(CLOSE, SMA100s) ] SMA100_cross_sells = [ True if sell_condition(close, sma) else False for close, sma in zip(CLOSE, SMA100s) ] SMA200_cross_buys = [ True if buy_condition(close, sma) else False for close, sma in zip(CLOSE, SMA200s) ] SMA200_cross_sells = [ True if sell_condition(close, sma) else False for close, sma in zip(CLOSE, SMA200s) ] ''' Exponential Moving Average (EMA) crosses, period 5,10,20,50,100,200 ''' # indicators EMA5s = [EMA(close, 5) for close in CLOSE] EMA10s = [EMA(close, 10) for close in CLOSE] EMA20s = [EMA(close, 20) for close in CLOSE] EMA50s = [EMA(close, 50) for close in CLOSE] EMA100s = [EMA(close, 100) for close in CLOSE] EMA200s = [EMA(close, 200) for close in CLOSE] # signals # def condition(close, ema): # return (close[-1] > ema[-1]) and (close[-2] <= ema[-2]) def buy_condition(close, ema): return (close[-1] > ema[-1]) and (close[-2] <= ema[-2]) def sell_condition(close, ema): return (close[-1] < ema[-1]) and (close[-2] >= ema[-2]) EMA5_cross_buys = [ True if buy_condition(close, ema) else False for close, ema in zip(CLOSE, EMA5s) ] EMA5_cross_sells = [ True if sell_condition(close, ema) else False for close, ema in zip(CLOSE, EMA5s) ] EMA10_cross_buys = [ True if buy_condition(close, ema) else False for close, ema in zip(CLOSE, EMA10s) ] EMA10_cross_sells = [ True if sell_condition(close, ema) else False for close, ema in zip(CLOSE, EMA10s) ] EMA20_cross_buys = [ True if buy_condition(close, ema) else False for close, ema in zip(CLOSE, EMA20s) ] EMA20_cross_sells = [ True if sell_condition(close, ema) else False for close, ema in zip(CLOSE, EMA20s) ] EMA50_cross_buys = [ True if buy_condition(close, ema) else False for close, ema in zip(CLOSE, EMA50s) ] EMA50_cross_sells = [ True if sell_condition(close, ema) else False for close, ema in zip(CLOSE, EMA50s) ] EMA100_cross_buys = [ True if buy_condition(close, ema) else False for close, ema in zip(CLOSE, EMA100s) ] EMA100_cross_sells = [ True if sell_condition(close, ema) else False for close, ema in zip(CLOSE, EMA100s) ] EMA200_cross_buys = [ True if buy_condition(close, ema) else False for close, ema in zip(CLOSE, EMA200s) ] EMA200_cross_sells = [ True if sell_condition(close, ema) else False for close, ema in zip(CLOSE, EMA200s) ] ''' Average Directional Movement Index (ADX), period 14 ''' # indicators ADXs = [ ADX(high, low, close, 14) for high, low, close in zip(HIGH, LOW, CLOSE) ] # signals # adx[0] is mDI, adx[1] is pDI, adx[2] is actual ADX def bullish_condition(adx): # Bullish strong trend cross return (adx[2][-1] > 20) and (adx[1][-1] > adx[0][-1]) and ( adx[1][-2] <= adx[0][-2]) def bearish_condition(adx): # Bearish strong trend cross return (adx[2][-1] > 20) and (adx[1][-1] < adx[0][-1]) and ( adx[1][-2] >= adx[0][-2]) ADX_bullish_crosses = [ True if bullish_condition(adx) else False for adx in ADXs ] ADX_bearish_crosses = [ True if bearish_condition(adx) else False for adx in ADXs ] ''' Moving Average Convergence Divergence (MACD) fast=12, slow=26 ''' # indicator EMA12s = [EMA(close, 12) for close in CLOSE] EMA26s = [EMA(close, 26) for close in CLOSE] MACDs = [[(a - b) if b is not None else None for a, b in zip(EMA12, EMA26)] for EMA12, EMA26 in zip(EMA12s, EMA26s)] # signals def bullish_condition(MACD): # Bullish zero cross which sustains for 2 days (reduce false signals) return (MACD[-3] <= 0) and (MACD[-2] > 0) and (MACD[-1] > 0) def bearish_condition(MACD): # Bearish zero cross return (MACD[-3] >= 0) and (MACD[-2] < 0) and (MACD[-1] < 0) MACD_bullish_zero_cross = [ True if bullish_condition(MACD) else False for MACD in MACDs ] MACD_bearish_zero_cross = [ True if bearish_condition(MACD) else False for MACD in MACDs ] ''' Commodity Channel Index (CCI), period 14 ''' # indicator CCIs = [ CCI(high, low, close, 14) for high, low, close in zip(HIGH, LOW, CLOSE) ] # signals def bullish_condition(CCI): return (CCI[-1] > 100) and (CCI[-2] <= 100) def bearish_condition(CCI): return (CCI[-1] < -100) and (CCI[-2] >= -100) CCI_emerging_bulls = [ True if bullish_condition(CCI) else False for CCI in CCIs ] CCI_emerging_bears = [ True if bearish_condition(CCI) else False for CCI in CCIs ] ''' ################ MOMENTUM ################ Relative Strength Index (RSI), period 14 ''' # indicator RSIs = [RSI(close) for close in CLOSE] # signals def bullish_reversal(rsi, sma200, close): # Uptrend and cross 30 to become oversold (Bullish) return (close[-1] > sma200[-1]) and (rsi[-2] >= 30) and (rsi[-1] < 30) def bearish_reversal(rsi, sma200, close): # Downtrend and cross 70 to become overbought (Bearish) return (close[-1] < sma200[-1]) and (rsi[-2] <= 70) and (rsi[-1] > 70) def underbought_uptrend(rsi, sma200, close): # Uptrend and underbought return (close[-1] > sma200[-1]) and (rsi[-1] < 50) def undersold_downtrend(rsi, sma200, close): # Downtrend and undersold return (close[-1] < sma200[-1]) and (rsi[-1] > 50) RSI_bullish_reversal = [ True if bullish_reversal(rsi, sma200, close) else False for rsi, sma200, close in zip(RSIs, SMA200s, CLOSE) ] RSI_bearish_reversal = [ True if bearish_reversal(rsi, sma200, close) else False for rsi, sma200, close in zip(RSIs, SMA200s, CLOSE) ] RSI_underbought_uptrend = [ True if underbought_uptrend(rsi, sma200, close) else False for rsi, sma200, close in zip(RSIs, SMA200s, CLOSE) ] RSI_undersold_downtrend = [ True if undersold_downtrend(rsi, sma200, close) else False for rsi, sma200, close in zip(RSIs, SMA200s, CLOSE) ] ''' Stochastic Oscillator, fast 14, slow 3 ''' # indicators StochOscs = [ StochOsc(close, high, low, 14, 3) for close, high, low in zip(CLOSE, HIGH, LOW) ] # signals # stochosc[0] is Ks, stochosc[1] is Ds def bullish_cross(stochosc): # K (fast) cross D (slow) from below return (stochosc[0][-2] <= stochosc[1][-2]) and (stochosc[0][-1] > stochosc[1][-1]) def bearish_cross(stochosc): # K (fast) cross D (slow) from above return (stochosc[0][-2] >= stochosc[1][-2]) and (stochosc[0][-1] < stochosc[1][-1]) StochOsc_bullish_cross = [ True if bullish_cross(stochosc) else False for stochosc in StochOscs ] StochOsc_bearish_cross = [ True if bearish_cross(stochosc) else False for stochosc in StochOscs ] ''' Williams %R, 14 period ''' # indicator WilliamsRs = [ WilliamsR(high, low, close) for high, low, close in zip(HIGH, LOW, CLOSE) ] # signals def bullish(wr, close, sma100): # Overbought price action return (wr[-1] > -20) and (close[-1] > sma100[-1]) and ( close[-2] <= sma100[-2]) def bearish(wr, close, sma100): # Oversold price action return (wr[-1] < -80) and (close[-1] < sma100[-1]) and ( close[-2] >= sma100[-2]) WilliamsR_uptrend = [ True if bullish(wr, close, sma100) else False for wr, close, sma100 in zip(WilliamsRs, CLOSE, SMA100s) ] WilliamsR_downtrend = [ True if bearish(wr, close, sma100) else False for wr, close, sma100 in zip(WilliamsRs, CLOSE, SMA100s) ] ''' Ultimate Oscillator, periods 20,40,80 ''' # indicator UltiOscs = [ UltiOsc(high, low, close, 20, 40, 80) for high, low, close in zip(HIGH, LOW, CLOSE) ] # signals def bullish_cross(ultiosc): # Bullish center cross return (ultiosc[-1] > 50) and (ultiosc[-2] <= 50) def bearish_cross(ultiosc): # Bearish center cross return (ultiosc[-1] < 50) and (ultiosc[-2] >= 50) def bullish_reversal(ultiosc): # Bullish reversal from oversold return (ultiosc[-1] < 30) and (ultiosc[-2] >= 30) def bearish_reversal(ultiosc): # Bearish reversal from overbought return (ultiosc[-1] > 70) and (ultiosc[-2] >= 70) UltiOsc_bullish_cross = [ True if bullish_cross(ultiosc) else False for ultiosc in UltiOscs ] UltiOsc_bearish_cross = [ True if bearish_cross(ultiosc) else False for ultiosc in UltiOscs ] UltiOsc_bullish_reversal = [ True if bullish_reversal(ultiosc) else False for ultiosc in UltiOscs ] UltiOsc_bearish_reversal = [ True if bearish_reversal(ultiosc) else False for ultiosc in UltiOscs ] ''' ################ VOLUME ################ Accumulation / Distribution Index (ADI) ''' # indicator ADIs = [ ADI(high, low, close, vol) for high, low, close, vol in zip(HIGH, LOW, CLOSE, VOL) ] def bullish_trend(close, adi, sma200): # bullish trend confirmation return (close[-1] > sma200[-1]) and (close[-2] <= sma200[-2]) and ( adi[-1] > adi[-2]) def bearish_trend(close, adi, sma200): # bearish trend confirmation return (close[-1] < sma200[-1]) and (close[-2] >= sma200[-2]) and ( adi[-1] < adi[-2]) ADI_bullish_trend_confo = [ True if bullish_trend(close, adi, sma200) else False for close, adi, sma200 in zip(CLOSE, ADIs, SMA200s) ] ADI_bearish_trend_confo = [ True if bearish_trend(close, adi, sma200) else False for close, adi, sma200 in zip(CLOSE, ADIs, SMA200s) ] ''' On-Balance Volume (OBV) ''' # indicator OBVs = [OBV(close, vol) for close, vol in zip(CLOSE, VOL)] # signals def bullish_trend(obv): return (obv[-1] > obv[-2]) and (obv[-2] > obv[-3]) def bearish_trend(obv): return (obv[-1] < obv[-2]) and (obv[-2] < obv[-3]) OBV_bullish_trend_confo = [ True if bullish_trend(obv) else False for obv in OBVs ] OBV_bearish_trend_confo = [ True if bearish_trend(obv) else False for obv in OBVs ] ''' ################ VOLATILITY ################ Bollinger Bands (BB), 20 period ''' # indicator + signal BBs = [BB(close, 20) for close in CLOSE] BB_bullish_reversal = [True if bb[1][-1] == 1 else False for bb in BBs] BB_bearish_reversal = [True if bb[0][-1] == 1 else False for bb in BBs] ''' Execution ''' for i in range(0, nMarkets - 1): future_name = markets[i + 1] # # Trend following # if (SMA5_cross_buys[i] == True) or (SMA10_cross_buys[i] == True) or (SMA20_cross_buys[i] == True) or (SMA50_cross_buys[i] == True) or (SMA100_cross_buys[i] == True) or (SMA200_cross_buys == True): # pos[i+1] = 1 # if (SMA5_cross_sells[i] == True) or (SMA10_cross_sells[i] == True) or (SMA20_cross_sells[i] == True) or (SMA50_cross_sells[i] == True) or (SMA100_cross_sells[i] == True) or (SMA200_cross_sells == True): # pos[i+1] = -1 # Mean reverting # if (SMA5_cross_buys[i] == True) or (SMA10_cross_buys[i] == True) or (SMA20_cross_buys[i] == True) or (SMA50_cross_buys[i] == True) or (SMA100_cross_buys[i] == True) or (SMA200_cross_buys == True): # pos[i+1] = -1 # if (SMA5_cross_sells[i] == True) or (SMA10_cross_sells[i] == True) or (SMA20_cross_sells[i] == True) or (SMA50_cross_sells[i] == True) or (SMA100_cross_sells[i] == True) or (SMA200_cross_sells == True): # pos[i+1] = 1 # # Trend following # if (EMA5_cross_buys[i] == True) or (EMA10_cross_buys[i] == True) or (EMA20_cross_buys[i] == True) or (EMA50_cross_buys[i] == True) or (EMA100_cross_buys[i] == True) or (EMA200_cross_buys == True): # pos[i+1] = 1 # if (EMA5_cross_sells[i] == True) or (EMA10_cross_sells[i] == True) or (EMA20_cross_sells[i] == True) or (EMA50_cross_sells[i] == True) or (EMA100_cross_sells[i] == True) or (EMA200_cross_sells == True): # pos[i+1] = -1 # # Mean-reverting # if (EMA5_cross_buys[i] == True) or (EMA10_cross_buys[i] == True) or (EMA20_cross_buys[i] == True) or (EMA50_cross_buys[i] == True) or (EMA100_cross_buys[i] == True) or (EMA200_cross_buys == True): # pos[i+1] = -1 # if (EMA5_cross_sells[i] == True) or (EMA10_cross_sells[i] == True) or (EMA20_cross_sells[i] == True) or (EMA50_cross_sells[i] == True) or (EMA100_cross_sells[i] == True) or (EMA200_cross_sells == True): # pos[i+1] = 1 # if ADX_bullish_crosses[i] == True: # pos[i+1] = 1 # elif ADX_bearish_crosses[i] == True: # pos[i+1] = -1 # if MACD_bullish_zero_cross[i] == True: # pos[i+1] = 1 # elif MACD_bearish_zero_cross[i] == True: # pos[i+1] = -1 # if CCI_emerging_bulls[i] == True: # pos[i+1] = 1 # elif CCI_emerging_bears[i] == True: # pos[i+1] = -1 # if RSI_bullish_reversal[i] == True: # pos[i+1] = 1 # elif RSI_bearish_reversal[i] == True: # pos[i+1] = -1 # if StochOsc_bullish_cross[i] == True: # pos[i+1] = 1 # elif StochOsc_bearish_cross[i] == True: # pos[i+1] = -1 # if WilliamsR_uptrend[i] == True: # pos[i+1] = 1 # elif WilliamsR_downtrend[i] == True: # pos[i+1] = -1 # if UltiOsc_bullish_cross[i] == True: # pos[i+1] = 1 # elif UltiOsc_bearish_cross[i] == True: # pos[i+1] = -1 # if UltiOsc_bullish_reversal[i] == True: # pos[i+1] = 1 # elif UltiOsc_bearish_reversal[i] == True: # pos[i+1] = -1 # if ADI_bullish_trend_confo[i] == True: # pos[i+1] = lweights[future_name] # elif ADI_bearish_trend_confo[i] == True: # pos[i+1] = sweights[future_name] # if OBV_bullish_trend_confo[i] == True: # pos[i+1] = 1 # elif OBV_bearish_trend_confo[i] == True: # pos[i+1] = -1 # # Mean-reverting # if BB_bullish_reversal[i] == True: # pos[i+1] = 1 # elif BB_bearish_reversal[i] == True: # pos[i+1] = -1 # # Trend-following if BB_bullish_reversal[i] == True: pos[i + 1] = sweights[future_name] elif BB_bearish_reversal[i] == True: pos[i + 1] = lweights[future_name] elif settings['model'] == 'LIGHTGBM': for i in range(0, nMarkets - 1): future_name = markets[i + 1] if future_name in [ "CASH", "F_ED", "F_UZ", "F_SS", "F_ZQ", "F_EB", "F_VW", "F_F" ]: feature_ADI = ADI(HIGH[i], LOW[i], CLOSE[i], VOL[i]) feature_WilliamsR = WilliamsR(HIGH[i], LOW[i], CLOSE[i]) feature_BB_high_crosses, feature_BB_low_crosses = BB( CLOSE[i], 10) feature_CCI = CCI(LOW[i], CLOSE[i], VOL[i], 10) features = np.array([[ OPEN[i][-1], HIGH[i][-1], LOW[i][-1], CLOSE[i][-1], VOL[i][-1], feature_ADI[-1], feature_WilliamsR[-1], feature_BB_high_crosses[-1], feature_BB_low_crosses[-1], feature_CCI[-1], CLOSE[i][-2], CLOSE[i][-3], ]]) model_dir = f"./data/lgb_models/{markets[i+1]}_model" prediction = get_lgb_prediction(model_dir, features)[0] if prediction == 1: pos[i + 1] = lweights[future_name] elif prediction == -1: pos[i + 1] = sweights[future_name] elif settings['model'] == 'sentiment': ''' How sentiment of tweets from Bloomberg/Trump affect VIX, Gold and Treasuries ''' for i in range(0, nMarkets - 1): future_name = markets[i + 1] if future_name in ['F_GC']: #'F_VX','F_GC','F_TU' sentiment = sentiment_data[future_name] today = datetime.strptime(str(DATE[-1]), '%Y%m%d').date() if (today - sentiment['DATE'].tolist()[0] ).days > 30: # at least 30 days for training train = sentiment[sentiment['DATE'] < today] test = sentiment[sentiment['DATE'] == today] trainY = train['CLOSE'] del train['DATE'], train['CLOSE'] trainX = train del test['DATE'], test['CLOSE'] model = RandomForestRegressor() model.fit(trainX, trainY) pred_CLOSE = model.predict(test)[0] if pred_CLOSE > CLOSE[i][-2]: pos[i + 1] = 1 else: pos[i + 1] = -1 elif settings['model'] == 'covid': ''' How no. of covid cases in each country affects their overall markets 'sharpe': 1.3048, 'sortino': 2.3477, avg longs per day: 1.35 , avg shorts per day: 6.6 ''' for i in range(0, nMarkets - 1): country = None future_name = markets[i + 1] if future_name in ['F_ES', 'F_MD', 'F_NQ', 'F_RU', 'F_XX', 'F_YM']: country = 'US' elif future_name in ['F_AX', 'F_DM', 'F_DZ']: country = 'Germany' elif future_name == 'F_CA': country = 'France' elif future_name == 'F_LX': country = 'United Kingdom' elif future_name == 'F_FP': country = 'Finland' elif future_name == 'F_NY': country = 'Japan' elif future_name == 'F_PQ': country = 'Portugal' elif future_name in ['F_SH', 'F_SX']: country = 'Switzerland' if country: df = covid_data[covid_data['Country/Region'] == country].T.sum( axis=1).reset_index() df = df.iloc[1:] df['index'] = df['index'].apply(lambda x: x + "20") df['index'] = df['index'].apply( lambda x: datetime.strptime(x, '%m/%d/%Y').date()) future = pd.DataFrame({'DATE': DATE, 'CLOSE': CLOSE[i]}) future['CLOSE'] = future['CLOSE'].shift(-1) future['DATE'] = future['DATE'].apply( lambda x: datetime.strptime(str(x), '%Y%m%d').date()) df = pd.merge(df, future, left_on='index', right_on='DATE') df = df[df[0] != 0][[0, 'CLOSE']].rename(columns={0: "count"}) if len(df) > 10: reg = LinearRegression().fit( np.array(df['count'].values[:-1]).reshape(-1, 1), df['CLOSE'].values[:-1]) pred_CLOSE = reg.predict( np.array(df['count'].values[-1]).reshape(1, -1))[0] if pred_CLOSE > CLOSE[i][-2]: pos[i + 1] = 1 else: pos[i + 1] = -1 elif settings['model'] == 'ARIMA': for i in range(0, nMarkets - 1): try: if markets[i + 1] not in ARIMA_MODELS: model = auto_arima(np.log(CLOSE[i][:-1]), trace=False, error_action='ignore', suppress_warnings=True) ARIMA_MODELS[markets[i + 1]] = model.fit( np.log(CLOSE[i][:-1])) model = ARIMA_MODELS[markets[i + 1]].fit(np.log(CLOSE[i][:-1])) pred = model.predict(n_periods=1)[0] # print(markets[i+1],pred, np.log(CLOSE[i][-1])) pos[i + 1] = 1 if pred > np.log(CLOSE[i][-1]) else -1 except: pos[i + 1] = 0 print(f"Today's position in the {len(markets)} futures: {pos}") elif settings['model'] == 'GARCH': # Log return of the closing data #Prameters bound1 = 1 bound2 = 1 cor_dir = f'./data/garch_models/correlation.txt' with open(cor_dir) as f: cor_dict = json.load(f) log_return = np.diff(np.log(CLOSE)) #print(log_return) #log_return = log_return[~np.isnan(log_return)] #print(log_return[1]) for i in range(0, nMarkets - 1): train_Xs = log_return[i][:-1] #test_Xs = log_return[i][-1] sd = np.var(train_Xs) # define model model_dir = f'./data/garch_models/{markets[i+1]}_garch_model.txt' with open(model_dir) as f: params_dict = json.load(f) p = params_dict['order'][0] q = params_dict['order'][1] model = arch_model(train_Xs, p=p, q=q) model_fixed = model.fix(params_dict['params']) # forecast the test set forecasts = model_fixed.forecast() #expected = forecasts.mean.iloc[-1:]['h.1'] var = forecasts.variance.iloc[-1:]['h.1'] #print(type(variance)) if (cor_dict[markets[i + 1]] > 0.03): if (float(np.sqrt(var)) > bound1 * np.std(train_Xs)): pos[i] = 1 elif (float(np.sqrt(var)) < bound2 * np.std(train_Xs)): pos[i] = -1 else: pos[i] = 0 elif (cor_dict[markets[i + 1]] < -0.03): if (float(np.sqrt(var)) > bound1 * np.std(train_Xs)): pos[i] = -1 elif (float(np.sqrt(var)) < bound2 * np.std(train_Xs)): pos[i] = 1 else: pos[i] = 0 else: pos[i] = 0 # With the estimated return and variance, we can apply portfolio optimization #print((np.array(result) * np.array(truth)).sum() / len(result)) elif settings['model'] == 'fourier': #Parameters that filter the signal with specific range of signals #Note that the lower bound should be larger than 0 and upper bound smaller than 1 filter_type = 'customed' my_frequency_bound = [0.05, 0.2] filter_type = 'low' #Specify high/mid/low/customed for weekly signals, weekly to monthly signals, above monthly signals or customed frequency range if filter_type == 'high': frequency_bound = [0.2, 1] elif filter_type == 'mid': frequency_bound = [0.05, 0.2] elif filter_type == 'low': frequency_bound = [0, 0.05] elif filter_type == 'customed': frequency_bound = my_frequency_bound #Transform the close data by fourier filtering, only signals within the specific range remains transformed_close = [] for i in range(0, nMarkets - 1): signal = CLOSE[i][:-1] fft = np.fft.rfft(signal) T = 1 # sampling interval N = len(signal) f = np.linspace(0, 1 / T, N) fft_filtered = [] for j in range(int(N / 2)): if f[j] > frequency_bound[0] and f[j] < frequency_bound[1]: fft_filtered.append(fft[j]) else: fft_filtered.append(0) signal_filtered = np.fft.irfft(fft_filtered) transformed_close.append(list(signal_filtered)) periodLonger = 200 periodShorter = 40 smaLongerPeriod = np.nansum( np.array(transformed_close)[:, -periodLonger:], axis=1) / periodLonger smaShorterPeriod = np.nansum( np.array(transformed_close)[:, -periodShorter:], axis=1) / periodShorter longEquity = smaShorterPeriod > smaLongerPeriod shortEquity = ~longEquity pos_1 = np.zeros(nMarkets - 1) pos_1[longEquity] = 1 pos_1[shortEquity] = -1 pos = np.array([0] + list(pos_1)) elif settings['model'] == 'pearson': ''' Pairwise correlation, taking position based on the greatest variation from average of the past 50 periods of 50 days ''' #'sharpe': 0.57939, 'sortino': 0.9027189, 'returnYearly': 0.076509, 'volaYearly': 0.13205 # with allocation #avg longs per day: 6.343 , avg shorts per day: 6.746 d = {} ##Name of future : Close of all 88 futures names = [] ##names of all 88 future for i in range(0, nMarkets - 1): n = markets[i + 1] names.append(n) d[n] = (CLOSE[i]) d_corr = settings['historic_corr'] ## key = tuple of name of 2 futures, value = position to take for ((future1,future2),difference) d_position = {} for i in list(d_corr.keys()): f = i[0] s = i[1] tup = d_corr[i] l1 = d[f][-49:-1] ##take last 50 close l2 = d[s][-49:-1] ##take last 50 close corr, _ = pearsonr(l1, l2) change_f = d[f][-2] - d[f][-49] change_s = d[s][-2] - d[s][-49] diff = tup - corr if diff > 0.3: if change_f > change_s: d_position[i] = ( (-1, 1), diff ) ##assuming -1 means short while 1 means long else: d_position[i] = ((1, -1), diff) for i in range( len(names)): ##find position based on greatest variation diff = 0 pair = tuple() name = names[i] counter = 0 for k in list(d_position.keys()): if name in k: counter += 1 pair = k if counter == 1: if name == k[0]: if d_position[k][0][0] > 0: pos[i + 1] = lweights[name] else: pos[i + 1] = sweights[name] else: if d_position[k][0][1] > 0: pos[i + 1] = lweights[name] else: pos[i + 1] = sweights[name] elif settings['model'] == 'FASTDTW': #'sharpe': 4.8632971, 'sortino': 17.09129, 'returnYearly': 1.216714, 'volaYearly': 0.25018 # no allocation # avg longs per day: 0.328 , avg shorts per day: 0.281 d = {} ##Name of future : Close of all 88 futures names = [] ##names of all 88 future for i in range(0, nMarkets - 1): n = markets[i + 1] names.append(n) d[n] = (CLOSE[i]) d_dist = settings[ 'historic_dist'] ## key = tuple of name of 2 futures, value = average distance d_position = {} for i in list(d_dist.keys()): f = i[0] s = i[1] tup = d_dist[i] l1 = d[f][-49:-1] ##take last 50 close l2 = d[s][-49:-1] ##take last 50 close distance, _ = fastdtw(l1, l2) distance = distance / 50 change_f = d[f][-2] - d[f][-49] change_s = d[s][-2] - d[s][-49] diff = distance - tup threshold = 16 * tup if distance > threshold: if change_f > change_s: d_position[i] = ( (-1, 1), diff ) ##assuming -1 means short while 1 means long else: d_position[i] = ((1, -1), diff) for i in range( len(names)): ##find position based on greatest variation diff = 0 name = names[i] for k in list(d_position.keys()): if name in k: if d_position[k][1] > diff: diff = d_position[k][1] if name == k[0]: if d_position[k][0][0] > 0: pos[i + 1] = lweights[name] else: pos[i + 1] = sweights[name] else: if d_position[k][0][1] > 0: pos[i + 1] = lweights[name] else: pos[i + 1] = sweights[name] # check if latest economic data suggests downturn then activate short only strats print("Positions:", pos) if np.nansum(pos) > 0: pos = pos / np.nansum(abs(pos)) settings['longs'] = settings['longs'] + sum(1 for x in pos if x > 0) settings['shorts'] = settings['shorts'] + sum(1 for x in pos if x < 0) settings['days'] = settings['days'] + 1 return pos, settings
def application(): if request.method == 'POST': new_request = request.get_json(force=True) new_ticker = get_ticker(new_request) private_client = AuthenticatedClient(Data.API_Public_Key, Data.API_Secret_Key, Data.Passphrase) new_order = Order(private_client) position = OpenPosition(new_order) funds = Capital(private_client) indicator = Indicator() macd = MACD() candle_ticker: str stop_time: int candle_gra = int if position.get_position() and last_instance(): candle_ticker = new_order.get_key("product_id") stop_time = get_time(27976) candle_gra = 300 writer = open(Data.Time, "w") writer.write(str(time.time() + 5.0)) writer.close() elif position.get_position() is False: candle_ticker = new_ticker stop_time = get_time(83925) candle_gra = 900 try: indicator.set_candles(product=candle_ticker, callback=stop_time, begin=get_time(0), granularity=candle_gra) except ValueError as ve: print(ve.with_traceback()) except NameError as ne: print(ne.with_traceback()) indicator_list = [indicator, macd] try: for value in indicator_list: value.candles = indicator.candles value.set_indicator() value.set_dates() except Exception as e: print(e.with_traceback()) indicator_5m = Indicator() macd_5m = MACD() if position.get_position() is False: if macd.hist[-1] > macd.hist[-2]: try: indicator_5m.set_candles(product=new_ticker, callback=get_time(27976), begin=get_time(0), granularity=900) except ValueError as ve: print(ve.with_traceback()) else: indicator_5m = indicator macd_5m = macd volume_5m = VolSMA(timeperiod=20) bands2dev_5m = BB() bands1dev_5m = BB(ndbevup=1, nbdevdn=1) rsi_5m = RSI() ema_5m = EMA() momentum_5m = Momentum() indicators = [ indicator_5m, macd_5m, volume_5m, bands1dev_5m, bands2dev_5m, rsi_5m, ema_5m, momentum_5m ] try: for value in indicators: value.candles = indicator_5m.candles value.set_indicator() value.set_dates() except Exception as e: print(e.with_traceback()) strategy_5m = Strategy(indicator_5m, macd_5m, bands1dev_5m, bands2dev_5m, volume_5m, rsi_5m, ema_5m, new_order) try: strategy_5m.strategy(-1) except Exception as e: print(e.with_traceback()) trade_side: str trade_product: str trade_funds: str if (new_order.is_bottom()) and (position.get_position() is False): trade_side = "buy" trade_product = new_ticker trade_funds = funds.get_capital() elif (new_order.is_top()) and (position.get_position()): trade_side = "sell" trade_product = new_order.get_key("product_id") trade_funds = get_size(trade_product, new_order.get_key("filled_size")) try: new_trade = private_client.place_market_order( product_id=trade_product, side=trade_side, funds=trade_funds) writer = open(Data.Path, "w") writer.write(new_trade['id']) writer.close() writer = open(Data.Time, "w") writer.write(new_trade['done_at']) writer.close() except NameError as ne: print(ne.with_traceback()) except KeyError as ke: print(ke.with_traceback()) return 'success', 200 elif request.method == 'GET': return redirect('http://3.218.228.129/login') else: abort(400)
from indicators import EMA emashort = EMA([3]) emalong = EMA([16])
import indicators.EMA as ema if __name__ == '__main__': # updater = indicators.MySQLIndicatorsUpdate('AAPL', 'ma', 'ema12') # ema = ema.EMA('AAPL', 12) updater = indicators.MySQLIndicatorsUpdate('AAPL', 'ma', 'ema12') ema = ema.EMA('AAPL', 12) for dtime, value in ema.get_all(): updater.insert(dtime, value) updater.commit()