Skip to content

Commit

Permalink
Merge branch 'support_resistance_indicator'
Browse files Browse the repository at this point in the history
  • Loading branch information
saleh-mir committed Jun 30, 2024
2 parents f0e8b42 + 3bd634e commit 37efdec
Show file tree
Hide file tree
Showing 3 changed files with 130 additions and 0 deletions.
1 change: 1 addition & 0 deletions jesse/indicators/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,3 +178,4 @@
from .waddah_attr_explosion import waddah_attar_explosion
from .stiffness import stiffness
from .ttm_squeeze import ttm_squeeze
from .support_resistance_with_break import support_resistance_with_breaks
117 changes: 117 additions & 0 deletions jesse/indicators/support_resistance_with_break.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
from collections import namedtuple

import numpy as np
from .ema import ema

SupportResistanceWithBreaks = namedtuple('SupportResistanceWithBreaks', ['support', 'resistance', 'red_break', 'green_break', 'bear_wick', 'bull_wick'])


def support_resistance_with_breaks(candles: np.ndarray, left_bars: int = 15, right_bars: int = 15, vol_threshold: int = 20) -> SupportResistanceWithBreaks:
"""
support_resistance_with_breaks
@author LuxAlgo
credits: https://www.tradingview.com/script/JDFoWQbL-Support-and-Resistance-Levels-with-Breaks-LuxAlgo
:param candles: np.ndarray
:param left_bars: int - default: 15
:param right_bars: int - default: 15
:param vol_threshold: int - default: 20
:return: SupportResistanceWithBreaks(support, resistance, red_break, green_break, bear_wick, bull_wick)
"""
resistance = _resistance(candles[:, 3], left_bars, right_bars)
support = _support(candles[:, 4], left_bars, right_bars)

short = ema(candles[:, 5], 5)
long = ema(candles[:, 5], 10)
osc = 100 * (short - long) / long

last_candles = candles[0]

red_break = True if last_candles[2] < support and not abs(
last_candles[1] - last_candles[2]) < abs(last_candles[1] - last_candles[3]) and osc > vol_threshold else False
green_break = True if last_candles[2] > resistance and abs(
last_candles[1] - last_candles[4]) > abs(last_candles[1] - last_candles[2]) and osc > vol_threshold else False

bull_wick = True if last_candles[2] > resistance and abs(last_candles[1] - last_candles[4]) > abs(last_candles[1] - last_candles[2]) else False
bear_wick = True if last_candles[2] < support and abs(last_candles[1] - last_candles[2]) < abs(last_candles[1] - last_candles[3]) else False

return SupportResistanceWithBreaks(support, resistance, red_break, green_break, bear_wick, bull_wick)


def _resistance(source, left_bars, right_bars):
pivot_highs = [None] * len(source) # Initialize result list with None

for i in range(left_bars, len(source) - right_bars):
is_pivot_high = True

# Check left bars for higher high
for j in range(1, left_bars + 1):
if source[i] <= source[i - j]:
is_pivot_high = False
break

# Check right bars for higher high
if is_pivot_high:
for j in range(1, right_bars + 1):
if source[i] <= source[i + j]:
is_pivot_high = False
break

if is_pivot_high:
is_pivot_high = source[i]

pivot_highs[i] = is_pivot_high

next_valid = None
first_value = None
for i in range(len(pivot_highs)):
if pivot_highs[i] is False:
pivot_highs[i] = next_valid
elif pivot_highs[i] is not None: # Update next_valid if it's not False or None
next_valid = pivot_highs[i]
first_value = i if first_value is None else first_value

pivot_highs[:first_value - 1] = [pivot_highs[first_value]] * len(pivot_highs[:first_value - 1])
pivot_highs[-right_bars:] = [pivot_highs[-right_bars - 1]] * len(pivot_highs[-right_bars:])

return pivot_highs[-1]


def _support(source, left_bars, right_bars):
pivot_lows = [None] * len(source) # Initialize result list with None

for i in range(left_bars, len(source) - right_bars):
is_pivot_low = True

# Check left bars for lower low
for j in range(1, left_bars + 1):
if source[i] >= source[i - j]:
is_pivot_low = False
break

# Check right bars for lower low
if is_pivot_low:
for j in range(1, right_bars + 1):
if source[i] >= source[i + j]:
is_pivot_low = False
break

if is_pivot_low:
is_pivot_low = source[i]

pivot_lows[i] = is_pivot_low

next_valid = None
first_value = None
for i in range(len(pivot_lows)):
if pivot_lows[i] is False:
pivot_lows[i] = next_valid
elif pivot_lows[i] is not None: # Update next_valid if it's not False or None
next_valid = pivot_lows[i]
first_value = i if first_value is None else first_value

pivot_lows[:first_value - 1] = [pivot_lows[first_value]] * len(pivot_lows[:first_value - 1])
pivot_lows[-right_bars:] = [pivot_lows[-right_bars - 1]] * len(pivot_lows[-right_bars:])

return pivot_lows[-1]
12 changes: 12 additions & 0 deletions tests/test_indicators.py
Original file line number Diff line number Diff line change
Expand Up @@ -2358,3 +2358,15 @@ def test_ttm_squeeze():
result = ta.ttm_squeeze(candles)

assert result == True


def test_support_resistance_with_breaks():
candles = np.array(test_candles_19)
result = ta.support_resistance_with_breaks(candles)

assert result.support == 116.26
assert result.resistance == 288.41
assert result.red_break == False
assert result.green_break == False
assert result.bear_wick == False
assert result.bull_wick == False

0 comments on commit 37efdec

Please sign in to comment.