Quantopian's community platform is shutting down. Please read this post for more information and download your code.
Back to Community
Candlestick Patterns

I'm surprised no one built out a candlestick algorithm. For those who aren't familiar with candlesticks, it's a bit of a hokey analysis that looks at patterns between the open, close, high and low price of a stock at some arbitrary time interval to determine whether the stock is likely to go up or down during the next period.

In my opinion, its popularity comes from the fact that the analysis is subjective enough to claim a kind of accuracy that is difficult to challenge empirically. Also, it produces pretty graphs.

I replicated candle stick analysis in the algorithm below. I boiled down the patterns to 4 factors.
1. Whether the stock ended higher or lower at end of day
2. Relative size of the high wick
3. How big the body is
4. Relative size of the low wick

The patterns I used for matching are the patterns indicated in the website below. The algorithm is setup in such a way that these patterns can easily be changed or new patterns added.

http://www.swing-trade-stocks.com/candlestick-patterns.html

The inputs required, apart from the patterns you're looking to match, is what you consider a big or small body and wick size. I was thinking about putting in some relative measure (5% movement in a day is large?) but chose to keep it simple with an absolute value instead.

Obviously the results are less than impressive but if someone really believes in candle stick analysis, that person can easily build on this. Also, this can pretty easily be expanded to analyze candles and trade multiple stocks.

Does anyone know of a way to plot candlesticks on a graph as an addendum to the graph produced?

7 responses

Hello Branko,

I have played a little with plotting candle charts with matplotlib (see below) but this is not possible in Quantopian. See http://matplotlib.org/examples/pylab_examples/finance_demo.html for more information.

P.

Seems like Quantopian is now blocking use of eq, hash, len, and getitem. Any suggestions for what to replace these with?

ta-lib has candlestick pattern recognition indicators:

CDL2CROWS Two Crows
CDL3BLACKCROWS Three Black Crows
CDL3INSIDE Three Inside Up/Down
CDL3LINESTRIKE Three-Line Strike
CDL3OUTSIDE Three Outside Up/Down
CDL3STARSINSOUTH Three Stars In The South
CDL3WHITESOLDIERS Three Advancing White Soldiers
CDLABANDONEDBABY Abandoned Baby
CDLADVANCEBLOCK Advance Block
CDLBELTHOLD Belt-hold
CDLBREAKAWAY Breakaway
CDLCLOSINGMARUBOZU Closing Marubozu
CDLCONCEALBABYSWALL Concealing Baby Swallow
CDLCOUNTERATTACK Counterattack
CDLDARKCLOUDCOVER Dark Cloud Cover
CDLDOJI Doji
CDLDOJISTAR Doji Star
CDLDRAGONFLYDOJI Dragonfly Doji
CDLENGULFING Engulfing Pattern
CDLEVENINGDOJISTAR Evening Doji Star
CDLEVENINGSTAR Evening Star
CDLGAPSIDESIDEWHITE Up/Down-gap side-by-side white lines
CDLGRAVESTONEDOJI Gravestone Doji
CDLHAMMER Hammer
CDLHANGINGMAN Hanging Man
CDLHARAMI Harami Pattern
CDLHARAMICROSS Harami Cross Pattern
CDLHIGHWAVE High-Wave Candle
CDLHIKKAKE Hikkake Pattern
CDLHIKKAKEMOD Modified Hikkake Pattern
CDLHOMINGPIGEON Homing Pigeon
CDLIDENTICAL3CROWS Identical Three Crows
CDLINNECK In-Neck Pattern
CDLINVERTEDHAMMER Inverted Hammer
CDLKICKING Kicking
CDLKICKINGBYLENGTH Kicking - bull/bear determined by the longer marubozu
CDLLADDERBOTTOM Ladder Bottom
CDLLONGLEGGEDDOJI Long Legged Doji
CDLLONGLINE Long Line Candle
CDLMARUBOZU Marubozu
CDLMATCHINGLOW Matching Low
CDLMATHOLD Mat Hold
CDLMORNINGDOJISTAR Morning Doji Star
CDLMORNINGSTAR Morning Star
CDLONNECK On-Neck Pattern
CDLPIERCING Piercing Pattern
CDLRICKSHAWMAN Rickshaw Man
CDLRISEFALL3METHODS Rising/Falling Three Methods
CDLSEPARATINGLINES Separating Lines
CDLSHOOTINGSTAR Shooting Star
CDLSHORTLINE Short Line Candle
CDLSPINNINGTOP Spinning Top
CDLSTALLEDPATTERN Stalled Pattern
CDLSTICKSANDWICH Stick Sandwich
CDLTAKURI Takuri (Dragonfly Doji with very long lower shadow)
CDLTASUKIGAP Tasuki Gap
CDLTHRUSTING Thrusting Pattern
CDLTRISTAR Tristar Pattern
CDLUNIQUE3RIVER Unique 3 River
CDLUPSIDEGAP2CROWS Upside Gap Two Crows
CDLXSIDEGAP3METHODS Upside/Downside Gap Three Method

http://ta-lib.org/function.html

Great, thank you!

Hi,
I personally have been struggling to understand how exactly TA Lib defines those patterns.
Here I take the exemple of Dojis, but this can be replicated to all other indicators

From this TA-Lib Doji definition and the TA-Lib settings, it appears the definitions are often linked to the ten last candles

    const TA_CandleSetting TA_CandleDefaultSettings[] = {  
        /* real body is long when it's longer than the average of the 10 previous candles' real body */  
        { TA_BodyLong, TA_RangeType_RealBody, 10, 1.0 },  
        /* real body is very long when it's longer than 3 times the average of the 10 previous candles' real body */  
        { TA_BodyVeryLong, TA_RangeType_RealBody, 10, 3.0 },  
        /* real body is short when it's shorter than the average of the 10 previous candles' real bodies */  
        { TA_BodyShort, TA_RangeType_RealBody, 10, 1.0 },  
        /* real body is like doji's body when it's shorter than 10% the average of the 10 previous candles' high-low range */  
        { TA_BodyDoji, TA_RangeType_HighLow, 10, 0.1 },  
        /* shadow is long when it's longer than the real body */  
        { TA_ShadowLong, TA_RangeType_RealBody, 0, 1.0 },  
        /* shadow is very long when it's longer than 2 times the real body */  
        { TA_ShadowVeryLong, TA_RangeType_RealBody, 0, 2.0 },  
        /* shadow is short when it's shorter than half the average of the 10 previous candles' sum of shadows */  
        { TA_ShadowShort, TA_RangeType_Shadows, 10, 1.0 },  
        /* shadow is very short when it's shorter than 10% the average of the 10 previous candles' high-low range */  
        { TA_ShadowVeryShort, TA_RangeType_HighLow, 10, 0.1 },  
        /* when measuring distance between parts of candles or width of gaps */  
        /* "near" means "<= 20% of the average of the 5 previous candles' high-low range" */  
        { TA_Near, TA_RangeType_HighLow, 5, 0.2 },  
        /* when measuring distance between parts of candles or width of gaps */  
        /* "far" means ">= 60% of the average of the 5 previous candles' high-low range" */  
        { TA_Far, TA_RangeType_HighLow, 5, 0.6 },  
        /* when measuring distance between parts of candles or width of gaps */  
        /* "equal" means "<= 5% of the average of the 5 previous candles' high-low range" */  
        { TA_Equal, TA_RangeType_HighLow, 5, 0.05 }  
    };

so for a Doji should be defined with body below 10% of the average of the last 10 high-low ranges, but when I test it it seems only to recognize dojis as figures where body(t-1) = body(t) (true equality, and not 'more or less equal').

In addition to this I wonder whether a more "correct" definition would not be an absolute figure (perhaps calibrated on percentiles from the whole sample, not only the last 10)

Hi,
I personally have been struggling to understand how exactly TA Lib defines those patterns.
Here I take the exemple of Dojis, but this can be replicated to all other indicators

From this TA-Lib Doji definition and the TA-Lib settings, it appears the definitions are often linked to the ten last candles

    const TA_CandleSetting TA_CandleDefaultSettings[] = {  
        /* real body is long when it's longer than the average of the 10 previous candles' real body */  
        { TA_BodyLong, TA_RangeType_RealBody, 10, 1.0 },  
        /* real body is very long when it's longer than 3 times the average of the 10 previous candles' real body */  
        { TA_BodyVeryLong, TA_RangeType_RealBody, 10, 3.0 },  
        /* real body is short when it's shorter than the average of the 10 previous candles' real bodies */  
        { TA_BodyShort, TA_RangeType_RealBody, 10, 1.0 },  
        /* real body is like doji's body when it's shorter than 10% the average of the 10 previous candles' high-low range */  
        { TA_BodyDoji, TA_RangeType_HighLow, 10, 0.1 },  
        /* shadow is long when it's longer than the real body */  
        { TA_ShadowLong, TA_RangeType_RealBody, 0, 1.0 },  
        /* shadow is very long when it's longer than 2 times the real body */  
        { TA_ShadowVeryLong, TA_RangeType_RealBody, 0, 2.0 },  
        /* shadow is short when it's shorter than half the average of the 10 previous candles' sum of shadows */  
        { TA_ShadowShort, TA_RangeType_Shadows, 10, 1.0 },  
        /* shadow is very short when it's shorter than 10% the average of the 10 previous candles' high-low range */  
        { TA_ShadowVeryShort, TA_RangeType_HighLow, 10, 0.1 },  
        /* when measuring distance between parts of candles or width of gaps */  
        /* "near" means "<= 20% of the average of the 5 previous candles' high-low range" */  
        { TA_Near, TA_RangeType_HighLow, 5, 0.2 },  
        /* when measuring distance between parts of candles or width of gaps */  
        /* "far" means ">= 60% of the average of the 5 previous candles' high-low range" */  
        { TA_Far, TA_RangeType_HighLow, 5, 0.6 },  
        /* when measuring distance between parts of candles or width of gaps */  
        /* "equal" means "<= 5% of the average of the 5 previous candles' high-low range" */  
        { TA_Equal, TA_RangeType_HighLow, 5, 0.05 }  
    };

so for a Doji should be defined with body below 10% of the average of the last 10 high-low ranges, but when I test it it seems only to recognize dojis as figures where body(t-1) = body(t) (true equality, and not 'more or less equal').

In addition to this I wonder whether a more "correct" definition would not be an absolute figure (perhaps calibrated on percentiles from the whole sample, not only the last 10)

@ Jean-Baptiste Lepetit
I personally do found that majorities of the candlesticks pattern I tested on were incorrect.
I left my comments on Ta-Lib github and waiting some feedback. If you have the same issues, please feel free to add your comments.
https://github.com/mrjbq7/ta-lib/issues/119
I found that some bitcoin back testing also using Talib for candlestick. If they do not modify the code, I doubt how come there is no people complaining about it?