I'm trying to create a script that, from standard OHLC data, finds patterns. The specific pattern i'm looking for right now is sideways movement after a move up, here is an example:

So basically my code should detect when price is inside a box like the ones above.

I know this is not easy to do and i'm not looking for someone to give their code, i just need some help finding a general direction or some sources/library on this matter, if there is any.

My idea was the following: detect when price is rising, and if price, after rising, starts moving between an X and Y interval (so without going too much up or down), label it as a range (which is what i'm looking for). I think this should work, but i have no idea how to put that down in code.

Here is what i have:

import copy
import urllib
import numpy as np
import pandas as pd
import cfscrape
import json
import datetime
from datetime import datetime as dt

BU = cfscrape.create_scraper()
URL = "https://api.binance.com/api/v1/klines?&symbol=ADABTC&interval=1h&limit=250"

ResultRaw = BU.get(URL, timeout=(10, 15)).content
Result = json.loads(ResultRaw)

for x in Result:
    TimeUnix = float(x[0]) / float(1000)
    K = datetime.datetime.fromtimestamp(TimeUnix)
    x[0] = K

    Variation = Result.index(x)

    Previous = Variation-1

    Variation = ((float(x[4])-float(x[1]))/float(x[1]))*100


df = pd.DataFrame([x[:6] for x in Result], 
                  columns=['Date', 'Open', 'High', 'Low', 'Close', 'Volume'])

format = '%Y-%m-%d %H:%M:%S'
df['Date'] = pd.to_datetime(df['Date'], format=format)
df = df.set_index(pd.DatetimeIndex(df['Date']))
df["Open"] = pd.to_numeric(df["Open"],errors='coerce')
df["High"] = pd.to_numeric(df["High"],errors='coerce')
df["Low"] = pd.to_numeric(df["Low"],errors='coerce')
df["Close"] = pd.to_numeric(df["Close"],errors='coerce')
df["Volume"] = pd.to_numeric(df["Volume"],errors='coerce')

Here is what i'm doing:

  1. Retrieve data
  2. Make it JSON data
  3. For every row, determine how much the price changed in terms of percentage, this is what Variation does
  4. Make it a Pandas dataframe

Any kind of help is appreciated!

  • $\begingroup$ Thank you for your answer @noob2. My initial purpose was to find a way to detect bullish triangles/wedges/pennants, but seeing that finding such specific pattern from code might be too hard to do, i decided to do the following: if price surges and then it doesn't go down again but instead it starts moving in a range, detect that range $\endgroup$
    – Jack022
    Jul 4, 2020 at 17:26
  • 1
    $\begingroup$ tl;dr what i'm trying to do is to detect when price starts ranging/consolidate after a bullish wave $\endgroup$
    – Jack022
    Jul 4, 2020 at 17:27
  • 1
    $\begingroup$ might want to look into aggregating OHLC data into price bars, and take a look at the Triple Barrier method and trend scanning. the python package mlfinlab implements these (de Prado 2018 Advances in financial machine learning) $\endgroup$
    – develarist
    Jul 4, 2020 at 22:52
  • $\begingroup$ Taking a look into it, thank you! $\endgroup$
    – Jack022
    Jul 4, 2020 at 23:07
  • 1
    $\begingroup$ @Emma Yes, i tried there too, but without getting answers unfortunately $\endgroup$
    – Jack022
    Jul 8, 2020 at 9:30

2 Answers 2


As far as I know there is no library. With some other researchers, we implemented this 20 years ago in scheme (yes, it was long ago, when Lisp, and not python, was the language of AI).

Our methodology (that was really fast), was the following

  1. you need a time scale, one week for instance
  2. mark all the local minima and local maxima at the time scale
  3. now you need to form lines passing by two of them and not crossing the "price line", if you think a little bit about it; to be efficient
    • you can only join local minima together of local maxima together, hence you need one code that you can run twice, once you "inverted" the price (ie $\times (-1)$).
    • once you detect that the line linking $m_i$ to $m_j$ crosses the "price line", you can remove from your list a lot of $m_k$ where $k>j$ if they are above the $[m_i,m_j)$ line
  4. now you have a collection of lines linking two (not mandatorily consecutive) local minima $(m_i,m_j)$ together, you "just" have to
    • have the angle with the horizontal axe of each line
    • check that lines having one local minimum in common have the "same angle" (you need a threshold to make two angles different; if you want to be realistic, computing the correct threshold is tricky)
    • now you have a list of lines containing 3 local minima
    • you can iterate
  5. at the stage you have a large collection of lines, characterized by
    • a starting point and a stopping point (where they cross the line of price or one local extremum)
    • its angle with the $x$ axis
    • its number of "supporting points" (note that if you have 3 "aligned points", you have 3 different lines: 2 with 2 points and one with 3 points)
  6. you need to write a "regex" language to create combination of such lines, like
    • an open triangle is: one upper line and one lower line, with a positive open angle, spanning the at least 3 dates in common
    • a head-and-shoulders is made of three lines: two upper (resp. lower) lines with "almost symmetric" angles and an "almost horizontal" lower (resp. upper) line, spanning at least 5 dates in common

If you implement it, please send me a copy of your code ;{)}

[EDIT] It seems that there is a medium post, pointing on a quantopian code, that is very close to my description. Nevertheless, the code seems to be very poor.

For instance, here is one line of code to find local maxima (60 days) in pandas:


Whereas in the quantopian code they have 20 complex lines of code (should be 2 since they do min and max). My advice is to reimplement, frankly it is not that complex.

  • $\begingroup$ Thank you a lot for your answer! It was really really helpful. I would like to send you the code for you the check it out, but the harsh truth is that I still don't have any. I'm still at a stage where I have a lot of concepts in mind but no idea how to actually put any of them on code. Here are some of the (very theoretica) approaches I had in mind (next message) : $\endgroup$
    – Jack022
    Jul 5, 2020 at 21:00
  • $\begingroup$ 1) Creating a neural network, feeding it images of patterns i like and let it loop through charts to see if it can find the patterns I chose 2) A more mathematical approach which would involve using minima and maxima, just like you suggested 3) Find a way to convert ohlc data to a series of values that I can use to "quantify" that pattern, then I can loop through other charts and see if there are new patterns that have similar values to the one I "quantified" $\endgroup$
    – Jack022
    Jul 5, 2020 at 21:03
  • $\begingroup$ @Jack022 not sure a neural net will be efficient in this, the geometric approach would have my preference (I like NNets in general: arxiv.org/abs/2006.09611 but not for this) $\endgroup$
    – lehalle
    Jul 8, 2020 at 10:00
  • $\begingroup$ Yes indeed. I've been thinking about this approach and it seems the best one to go for now. My main focus and biggest trouble right now is putting it on Python code $\endgroup$
    – Jack022
    Jul 8, 2020 at 11:04
  • 1
    $\begingroup$ @Jack022 I updated my answer to reflect my comments on the link you found $\endgroup$
    – lehalle
    Jul 9, 2020 at 21:53

Could you possibly use the matrix flag labelling technique? The following provides some documentation and you can always design your own custom flags.

I think it will be a good tool to investigate: https://mlfinlab.readthedocs.io/en/latest/labeling/labeling_matrix_flags.html

  • $\begingroup$ Thank you a lot. This is a good resource. I'm taking a look $\endgroup$
    – Jack022
    Jul 10, 2020 at 8:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.