def csi(df, V, M, C): '''Commodity Selection Index(CSI) CSI suggest that the best commodities are: - high in directional movement (DMI indicator value) - high in volatility (Volatility Index value and ATR) - have reasonable margin requirements (relative to directional movement & volatility) - have reasonable commission rates Usage: Trade with high CSI values CSI = ADXR*ATR(14)(V/sqrt(M)*1/(150+C))*100 where: ADXR:Average Directional Movement Index Rating ATR(14):14-days Average True Range V:value of a 1 $ move(or the basic increment of ATR(14) in dollar) M:margin requirement in dollars C:commition in dollars Note: the result of the term 1/(150+C) must be carried to four decimal places ADXR = (ADT(today)+ADX(14 days ago))/2 ''' res = df[['high', 'low', 'close']].copy() res['ATR'] = atr(res, period=14)[['ATR']] res['ATR14'] = atr(res.shift(14), period=14)[['ATR']] res['ADXR'] = (res.ATR + res.ATR14) / 2 res['CSI'] = res.ADXR * res.ATR * (V / np.sqrt(M) * 1 / (150 + C)) * 100 return res[['CSI', 'ATR', 'ATR14', 'ADXR']]
def chandlier_exit(df): '''Chandlier Exit Make profits in the direction of trend development, calculate the stock price at the time of exit uptrend = Highest High(in the past 22 days)-3*ATR(for 22 days) downtrend = Lowest Low(in the past 22 days)+3*ATR(for 22 days) ''' res = df[['high', 'low', 'close']].copy() res['uptrend'] = ( res[['high']].rolling(22).max()).high - 3 * (atr(df, period=22).ATR) res['downtrend'] = ( res[['low']].rolling(22).min()).low + 3 * (atr(df, period=22).ATR) return res
def keltner_channels(df,n,halflife=14): '''Kelter Channels(Keltner Bands) The theory is that a movement that starts at one price band is likely to carry to the other. Go long when prices turn up at or below the lower band. Close your position if price turns down near the upper band or crosses to below the moving average. Go short when price turns down at or above the upper band. Close your position if price turns up near the lower band or crosses to above the moving average. Upper Band = Exponential MA of Closing Price + multiple of Average True Range Lower Band = Exponential MA of Closing Price - multiple of Average True Range ''' res = df[['close','high','low']].copy() res['upper_band'] = ema(res['close'],halflife)+atr(res).ATR*n res['lower_band'] = ema(res['close'],halflife)-atr(res).ATR*n return res
def atr_trailing_stop_signals(df,n=3): '''ATR Trailing Stop Signals Usage: Signals are used for exits: Exit your long position (sell) when price crosses below the ATR trailing stop line. Exit your short position (buy) when price crosses above the ATR trailing stop line. they can also be used to signal entries — in conjunction with a trend filter. steps: Calculate Average True Range ("ATR") Multiply ATR by your selected multiple — in our case 3 x ATR In an up-trend, subtract 3 x ATR from Closing Price and plot the result as the stop for the following day. If price closes below the ATR stop, add 3 x ATR to Closing Price — to track a Short trade Otherwise, continue subtracting 3 x ATR for each subsequent day until price reverses below the ATR stop. We have also built in a ratchet mechanism so that ATR stops cannot move lower during a Long trade nor rise during a Short trade. The HighLow option is a little different: 3xATR is subtracted from the daily High during an up-trend and added to the daily Low during a down-trend. ''' res = df[['close','high','low']].copy() res['ATR'] = atr(res).ATR res['stop'] = res.close-n*res.ATR res['trade'] = np.nan res['highoption'] = np.nan res['lowoption'] = np.nan for i in range(len(res.close)): while res.close.iloc[i]>=res.stop.iloc[i]: res.close.iloc[i] = res.close.iloc[i]-n*res.ATR.iloc[i] res.trade.iloc[i] = res.close.iloc[i]+n*res.ATR.iloc[i] res.highoption.iloc[i] = res.high.iloc[i]-n*res.ATR.iloc[i] res.lowoption.iloc[i] = res.low.iloc[i]+n*res.ATR.iloc[i] return res
def choppiness(df,n): '''Choppiness Index Choppiness Index = 100 * Log10{Sum(TrueRange,n) / [Maximum(TrueHigh,n) - Minimum(TrueLow,n)]} / Log10(n) ''' res = df[['high','low','close']].copy() res['sumTR'] = atr(res)['TR'].rolling(n).sum() res['maxtruehigh'] = res['high'].rolling(n).max() res['mintruelow'] = res['low'].rolling(n).min() res['choppiness'] = 100* (res.sumTR/(res.maxtruehigh-res.mintruelow)).apply(math.log,10) \ /math.log(n,10) return res
def asi(df, T=300): '''Accumulative Swing Indicator(ASI) ASI = 50*(Cy-C+0.5*(Cy-Oy)+0.25*(C-O))/R*(K/T) parameters: C = Today's closing price Cy = Yesterday's closing price Hy = Yesterday's highest price K = The greatest of: Hy - C and Ly - C L = Today's lowest price Ly = Yesterday's lowest price O = Today's opening price Oy = Yesterday's opening price R = This varies based on relationship between today's closing price and yesterday's high and low prices T = the maximum price changing during trade session Usage: ASI has positive value — uptrend. ASI has negative value — downtrend. ASI trend line breakout — validates a breakout on the price chart ''' #SI(i) = (50*(close[i-1]-close[i]+0.5*(close[i-1]-open[i-1]) # +0.25*(close[i]-open[i]))/R)*(K/T) #ASI(i) = SI(i-1)+SI(i) res = df[['close', 'open', 'high', 'low']].copy() res['temp1'] = -1 * res.close.diff() res['temp2'] = (res.close - res.open).shift() res['temp3'] = res.close - res.open #K=max((close[i-1]-close[i]),(low[i-1]-close[i])) res['K'] = np.nan for i in range(len(res) - 1): if res.close.iloc[i] >= res.low[i]: res.K.iloc[i + 1] = res.close.iloc[i] - res.close.iloc[i + 1] else: res.K.iloc[i + 1] = res.low.iloc[i] - res.close.iloc[i + 1] ''' R = TR - 0.5*ER + 0.25*SH TR = atr(df,period=14) if(Close[i+1] >= Low[i] && Close[i+1] <= High[i]) ER = 0; else { if(Close[i+1] > High[i]) ER = MathAbs(High[i] - Close[i+1]); if(Close[i+1] < Low[i]) ER = MathAbs(Low[i] - Close[i+1]); } SH = MathAbs(Close[i+1] - Open[i+1]); ''' res['TR'] = atr(df)[['ATR']] res['ER'] = np.nan for i in range(len(res) - 1): if res.close.iloc[i+1]>=res.low.iloc[i] and \ res.close.iloc[i+1]<=res.high.iloc[i]: res.ER.iloc[i] = 0 else: if res.close.iloc[i + 1] > res.high.iloc[i]: res.ER.iloc[i] = abs(res.high.iloc[i] - res.close.iloc[i + 1]) elif res.close.iloc[i + 1] < res.low.iloc[i]: res.ER.iloc[i] = abs(res.low.iloc[i] - res.close.iloc[i + 1]) res['SH'] = abs(res.close.shift(-1) - res.open.shift(-1)) res['R'] = res.TR - 0.5 * res.ER + 0.25 * res.SH res['SI'] = (50 * (res.temp1 + 0.5 * res.temp2 + 0.25 * res.temp3) / res.R) * (res.K / T) res['ASI'] = np.nan for i in range(len(res) - 1): res.ASI.iloc[i + 1] = res.SI.iloc[i + 1] + res.SI.iloc[i] return res.ASI