Skip to main content

trendln

Support and Resistance Trend lines Calculator for Financial Analysis

PyPI - Python Version PyPI - Version PyPI - Status PyPI - Downloads PyPI - License PyPI - Implementation CI GitHub stars

Note

This library can calculate and plot trend lines for any time series, not only for its primary intended purpose of financial analysis.

Changelog »


==> Check out this article on Programmatic Identification of Support/Resistance Trend lines with Python for details on how the library and its features are implemented and work.


Quick Start

Calculation Only

The calc_support_resistance function will calculate all support and resistance information including local extrema, average and their trend lines using several different methods:

import trendln
# this will serve as an example for security or index closing prices, or low and high prices
import yfinance as yf # requires yfinance - pip install yfinance
tick = yf.Ticker('^GSPC') # S&P500
hist = tick.history(period="max", rounding=True)
h = hist[-1000:].Close
mins, maxs = trendln.calc_support_resistance(h)
minimaIdxs, pmin, mintrend, minwindows = trendln.calc_support_resistance((hist[-1000:].Low, None)) #support only
mins, maxs = trendln.calc_support_resistance((hist[-1000:].Low, hist[-1000:].High))
(minimaIdxs, pmin, mintrend, minwindows), (maximaIdxs, pmax, maxtrend, maxwindows) = mins, maxs

Documentation for usage:

(minimaIdxs, pmin, mintrend, minwindows), (maximaIdxs, pmax, maxtrend, maxwindows) = \
	trendln.calc_support_resistance(
	# list/numpy ndarray/pandas Series of data as bool/int/float and if not a list also unsigned
	# or 2-tuple (support, resistance) where support and resistance are 1-dimensional array-like or one or the other is None
	# can calculate only support, only resistance, both for different data, or both for identical data
	h,

	# METHOD_NAIVE - any local minima or maxima only for a single interval (currently requires pandas)
	# METHOD_NAIVECONSEC - any local minima or maxima including those for consecutive constant intervals (currently requires pandas)
	# METHOD_NUMDIFF (default) - numerical differentiation determined local minima or maxima (requires findiff)
	extmethod = METHOD_NUMDIFF,
	
	# METHOD_NCUBED - simple exhaustive 3 point search (slowest)
	# METHOD_NSQUREDLOGN (default) - 2 point sorted slope search (fast)
	# METHOD_HOUGHPOINTS - Hough line transform optimized for points
	# METHOD_HOUGHLINES - image-based Hough line transform (requires scikit-image)
	# METHOD_PROBHOUGH - image-based Probabilistic Hough line transform (requires scikit-image)
	method=METHOD_NSQUREDLOGN,
	
	# window size when searching for trend lines prior to merging together
	window=125,
	
	# maximum percentage slope standard error
	errpct = 0.005,
	
	# for all METHOD_*HOUGH*, the smallest unit increment for discretization e.g. cents/pennies 0.01
	hough_scale=0.01,
	
	# only for METHOD_PROBHOUGH, number of iterations to run
	hough_prob_iter=10,
	
	# sort by area under wrong side of curve, otherwise sort by slope standard error
	sortError=False,
	
	# accuracy if using METHOD_NUMDIFF for example 5-point stencil is accuracy=4
	accuracy=2)
# if h is a 2-tuple with one value as None, then a 2-tuple is not returned, but the appropriate tuple instead
# minimaIdxs - sorted list of indexes to the local minima
# pmin - [slope, intercept] of average best fit line through all local minima points
# mintrend - sorted list containing (points, result) for local minima trend lines
	# points - list of indexes to points in trend line
	# result - (slope, intercept, SSR, slopeErr, interceptErr, areaAvg)
		# slope - slope of best fit trend line
		# intercept - y-intercept of best fit trend line
		# SSR - sum of squares due to regression
		# slopeErr - standard error of slope
		# interceptErr - standard error of intercept
		# areaAvg - Reimann sum area of difference between best fit trend line
		#   and actual data points averaged per time unit
# minwindows - list of windows each containing mintrend for that window

# maximaIdxs - sorted list of indexes to the local maxima
# pmax - [slope, intercept] of average best fit line through all local maxima points
# maxtrend - sorted list containing (points, result) for local maxima trend lines
	#see for mintrend above
# maxwindows - list of windows each containing maxtrend for that window

The get_extrema function will calculate all of the local minima and local maxima without performing the full trend line calculation.

minimaIdxs, maximaIdxs = trendln.get_extrema(hist[-1000:].Close)
maximaIdxs = trendln.get_extrema((None, hist[-1000:].High)) #maxima only
minimaIdxs, maximaIdxs = trendln.get_extrema((hist[-1000:].Low, hist[-1000:].High))

Documentation for usage:

minimaIdxs, maximaIdxs = trendln.get_extrema(
	h,
	extmethod=METHOD_NUMDIFF,
	accuracy=2)
# parameters and results are as per defined for calc_support_resistance

Plotting Calculations

The plot_support_resistance function will calculate and plot the average and top 2 support and resistance lines, along with marking extrema used with a maximum history length, and otherwise identical arguments to the calculation function.

fig = trendln.plot_support_resistance(hist[-1000:].Close) # requires matplotlib - pip install matplotlib
plt.savefig('suppres.svg', format='svg')
plt.show()
plt.clf() #clear figure

Documentation for usage:

fig = trendln.plot_support_resistance(
	hist, #as per h for calc_support_resistance
	xformatter = None, #x-axis data formatter turning numeric indexes to display output
	  # e.g. ticker.FuncFormatter(func) otherwise just display numeric indexes
	numbest = 2, #number of best support and best resistance lines to display
	fromwindows = True, #draw numbest best from each window, otherwise draw numbest across whole range
	pctbound = 0.1, # bound trend line based on this maximum percentage of the data range above the high or below the low
	extmethod = METHOD_NUMDIFF,
	method=METHOD_NSQUREDLOGN,
	window=125,
	errpct = 0.005,
	hough_prob_iter=10,
	sortError=False,
	accuracy=2)
# other parameters as per calc_support_resistance
# fig - returns matplotlib.pyplot.gcf() or the current figure

The plot_sup_res_date function will do the same as plot_support_resistance with help for nice formatting of dates based on a pandas date index.

idx = hist[-1000:].index
fig = trendln.plot_sup_res_date((hist[-1000:].Low, hist[-1000:].High), idx) #requires pandas
plt.savefig('suppres.svg', format='svg')
plt.show()
plt.clf() #clear figure

Documentation for usage:

fig = trendln.plot_sup_res_date( #automatic date formatter based on US trading calendar
	hist, #as per h for calc_support_resistance
	idx, #date index from pandas
	numbest = 2,
	fromwindows = True,
	pctbound = 0.1,
	extmethod = METHOD_NUMDIFF,
	method=METHOD_NSQUREDLOGN,
	window=125,
	errpct = 0.005,
	hough_scale=0.01,
	hough_prob_iter=10,
	sortError=False,
	accuracy=2)
# other parameters as per plot_support_resistance

Finally, for the above mentioned article, some figures were generated for reference material, while others use the library to demonstrate how it works. These can be generated as well:

trendln.plot_sup_res_learn('.', hist)

Documentation for usage:

trendln.plot_sup_res_learn( #draw learning figures, included for reference material only
	curdir, #base output directory for png and svg images, will be saved in 'data' subfolder
	hist) #pandas DataFrame containing Close and date index

Example output of plotting support resistance

Installation

Install trendln using pip:

$ pip install trendln --upgrade --no-cache-dir

Install trendln using conda:

$ conda install -c GregoryMorse trendln

Installation sanity check:

import trendln
#requires yfinance library install, not a package requirement, but used to assist with sanity check
#pip install yfinance
directory = '.' # a 'data' folder will be created here if not existing to store images
trendln.test_sup_res(directory) #simple tests that all methods are executing correct, assertion or other error indicates problem

Requirements

  • Python >= 2.7, 3.4+
  • numpy >= 1.15
  • findiff >= 0.7.0 (if using default numerical differentiation method)
  • scikit-image >= 0.14.0 (if using image-based Hough line transform or its probabilistic variant)
  • pandas >= 0.23.1 (if using date plotting function, or using naive minima/maxima methods)
  • matplotlib >= 2.2.4 (if using any plotting function)

License

trendln is distributed under the MIT License. See the LICENSE file in the release for details.

Support

Any questions, issues or ideas can kindly be submitted for review.

Gregory Morse gregory.morse@live.com

Metadata

Release files for trendln 0.1.18

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

Source distribution (sdist)

Source distribution for trendln 0.1.18
File Size Uploaded
trendln-0.1.18.tar.gz 36.3 kB Details

Built distribution (wheel)

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

Total release size: 60.5 kB

Release files / trendln-0.1.18.tar.gz

Download URL trendln-0.1.18.tar.gz
Size 36.3 kB
Tags Source
SHA-256 checksum
How to use checksums
f849cdb7561411fbd171e7a1b345770001e023000bf97c9f334f0cbb3ccb5a9b
BLAKE2b-256 checksum
How to use checksums
a7d1917bfea309f063f2037c7b8b526022c795a465d6f439f8245819dd9bf6d3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Apr 9, 2026.

Transparency log

Release files / trendln-0.1.18-py3-none-any.whl

Download URL trendln-0.1.18-py3-none-any.whl
Size 24.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
7d2982ef7de565494580a8bcca23cdd4ed239048b45a4861b88dbe793bc0a5e0
BLAKE2b-256 checksum
How to use checksums
431e61ddbea0b1c91015ca901e66e9460e004b103f9ca6b095fa5b4ae692076c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Apr 9, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.18 This release

2 release files

0.1.10

1 release file

0.1.8

1 release file

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