Skip to main content

pytrendline

About

Given a OHLC candlestick chart, pytrendline allows you to detect support and resistance lines formed by the High and Close price series.

pytrendline preview

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.

How the algorithm works

  1. Pivot points are identified in the candlestick chart.

  2. In each scan between points (i,j), pytrendln attempts to draw a line on top of the candlestick chart and checks the following:

  • What are the “points” that make up the trendline? For a trendline to be valid it must satisfy the minimum number of points specified in argument 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

Error between trendline and price

  • 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),
  1. Oftentimes, the trendline search finds trendlines that are almost identical in slope and last price and groups them. Because we might only care about the best scored trendline from each of these groups, the best one is identified and you can choose to discard the rest for your analysis.

Duplicate grouping

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.

  1. Results for all trendlines are returned into an easily sortable and filter-able Pandas dataframe.

Usage

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={}
)

Tuning algorithm parameters

DEFAULT_CONFIG within source file detect.py [TODO LINK] 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.iloc[-1].Close / 100,
   }
)

Plotting results

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.

Running example

You can run the example included in this repo to get a taste of what is possible with this library.

  1. Clone this github repo into a local directory.
  2. Install required libraries using
pip install -r requirements.txt 
  1. Run
python example.py

Installing library

Library can install using pip:

pip install trendln

Metadata

Release files for pytrendline 1.0.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pytrendline 1.0.1
File Size Uploaded
pytrendline-1.0.1.tar.gz 18.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for pytrendline 1.0.1
File Interpreter ABI Platform
pytrendline-1.0.1-py3-none-any.whl Python 3 none any Details

Total release size: 36.5 kB

Release files / pytrendline-1.0.1.tar.gz

Download URL pytrendline-1.0.1.tar.gz
Size 18.2 kB
Tags Source
SHA-256 checksum
How to use checksums
f8fe72c3d46860a7a498339125c90aebf275a11fd1cd95c08d4ef36f17020926
BLAKE2b-256 checksum
How to use checksums
7f89a07942eec52e2abf6f00f8739425f9482c959f71d949fb9dd97201c565b1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/3.4.1 importlib_metadata/4.5.0 pkginfo/1.7.0 requests/2.23.0 requests-toolbelt/0.9.1 tqdm/4.48.0 CPython/3.7.8

Release files / pytrendline-1.0.1-py3-none-any.whl

Download URL pytrendline-1.0.1-py3-none-any.whl
Size 18.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
3e0ac5ab03eabf2a05a35755dba05be2d91747d1ae9edfc9d3b6999a0f31a97c
BLAKE2b-256 checksum
How to use checksums
c1b942996698a140768fbd91e8cd56b2518792aa85fef8921b75d36679118c97
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/3.4.1 importlib_metadata/4.5.0 pkginfo/1.7.0 requests/2.23.0 requests-toolbelt/0.9.1 tqdm/4.48.0 CPython/3.7.8

Release history Release notifications | RSS feed

This release

1.0.1 This release

2 release files

1.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page