Given a OHLC candlestick chart, pytrendline allows you to detect support and resistance lines formed by the High and Close price series.
The trendline scanning algorithm scans for the existence of trendlines by attempting to draw lines between points [(0,1),(0,2),(0,3)...(0,N)] for the first iteration. Subsequent iteration attempts to draw lines between points [(1,2),(1,3),...(1,N)], then [(2,3),(2,4)...(2,N)] and so forth.
Because this operates by doing a full exhaustive search, the runtime is of cubic complexity O(N^3). If low latency is important and your use case is extremely large datasets, you might want to look into alternative algorithms / libraries. For picking up trendlines on day-trading use cases (small number of candles) or offline analysis it works great.
The algorithm also speeds up significantly if the search is narrowed down to only include lines with pivot points as one of the start or end points.
Note: pivot points are identified as local maximum or minimum points ie “troughs” and “peaks” in the candlestick chart.
Pivot points are identified in the candlestick chart.
In each scan between points (i,j), pytrendln attempts to draw a line on top of the candlestick chart and checks the following:
detect(...)
argument min_points_required
. A date in a trendline is determined to be a valid “point” if the distance between the drawn trendline and the candlestick price does not exceed max_allowable_error_pt_to_trend
Does the trendline cross over a candlestick body somewhere in its trajectory? If the trendline intersects some distance higher breakout_tolerance
above the candlestick body, we consider this line to be a breakout. Breakout trendlines are only considered valid if detect(...)
argument ignore_breakouts
is set to False
.
Checks if the trendline satisfies optional pivot point requirements. If not, the trendline is discarded.
A score is given to the trendline using scoring function specified in detect(...)
argument config
. The default scoring function scores trendlines higher if the mean distance between trendline and candle points are low and also gives additional favorability to a higher number of points.
Default scoring function:
"scoring_function": lambda candles, err_distances, num_points, slope: (util.avg_candle_range(candles) / util.mean(err_distances)) * (2.5 ** num_points),
This grouping is done by 2D clustering the set of (slope,last_price) pairs for all trendlines. Two trendlines are identified to be a part of the same group if both their slopes and last_price are within duplicate_grouping_threshold_slope
and duplicate_grouping_threshold_last_price
respectively.
For detecting trendlines, a Pandas dataframe containing OHLC data must be packaged into a pytrendline.CandlestickData
object and then passed on to pytrendline.detect(...)
# Package Candlestick Data
candles_df = pd.read_csv('./fixtures/example.csv')
candles_df['Date'] = pd.to_datetime(candles_df['Date'])
candlestick_data = pytrendline.CandlestickData(
df=candles_df,
time_interval="1m", # choose between 1m,3m,5m,10m,15m,30m,1h,1d
open_col="Open", # name of the column containing candle "Open" price
high_col="High", # name of the column containing candle "High" price
low_col="Low", # name of the column containing candle "Low" price
close_col="Close", # name of the column containing candle "Close" price
datetime_col="Date" # name of the column containing candle datetime price (use none if datetime is in index)
)
# Detect
results = pytrendline.detect(
candlestick_data=candlestick_data,
# Choose between BOTH, SUPPORT or RESISTANCE
trend_type=pytrendline.TrendlineTypes.BOTH,
# Specify if you require the first point of a trendline to be a pivot
first_pt_must_be_pivot=False,
# Specify if you require the last point of the trendline to be a pivot
last_pt_must_be_pivot=False,
# Specify if you require all trendline points to be pivots
all_pts_must_be_pivots=False,
# Specify if you require one of the trendline points to be global max or min price
trendline_must_include_global_maxmin_pt=False,
# Specify minimum amount of points required for trendline detection (NOTE: must be at least two)
min_points_required=3,
# Specify if you want to ignore prices before some date
scan_from_date=None,
# Specify if you want to ignore 'breakout' lines. That is, lines that interesect a candle
ignore_breakouts=True,
# Specify and override to default config (See docs on how)
config={}
)
DEFAULT_CONFIG within source file detect.py contains default parameters regarding thresholds for pivot detection, trendline detection, grouping, scoring, etc. All of these config parameters are a lambda taking candlestick data as input.
You can override a default by passing a new key string + lambda pair to the config
parameter in detect
.
results = detect(
…
config={
# Force the tolerance to be derived from last candle price
"max_allowable_error_pt_to_trend": lambda candles: candles.df.iloc[-1].Close / 100,
}
)
pytrendline provides a plot(...)
function to visualize the results in an interactive HTML chart generated with the aid of Bokeh.
outf = pytrendline.plot(
results=results,
filedir='.',
filename='example_output.html',
)
os.system("open " + outf)
In the resulting plot, pivot points are marked as green diamonds, best trendlines for each duplicate gruop is shown in solid dashed blue/orange, and non-best trendlines are shown in transaparent dotted blue/orange.
You can run the example included in this repo to get a taste of what is possible with this library.
pip install -r requirements.txt
python example.py
Library can install using pip:
pip install pytrendline