TA-Lib / ta-lib-python

Python wrapper for TA-Lib (http://ta-lib.org/).
http://ta-lib.github.io/ta-lib-python
Other
9.46k stars 1.74k forks source link

Examples of Candlestick Pattern Recognition #74

Open greencoder opened 9 years ago

greencoder commented 9 years ago

Do you know of any examples of using this library to do Candlestick Pattern Recognition? I'm struggling a bit trying to get started - I've got plenty of OHLCV data but I'm not sure how to use it here.

I'd be happy to help contribute working examples to this project's wiki if someone could help me get going.

mrjbq7 commented 9 years ago

There are quite a number of candlestick pattern recognition methods available, you can see a list here:

>>> import talib
>>> talib.get_function_groups()['Pattern Recognition']

Each one has some documentation available on how to call it, for example:

In [2]: ?talib.CDLTRISTAR
Type:        builtin_function_or_method
String form: <built-in function CDLTRISTAR>
Docstring:
CDLTRISTAR(open, high, low, close)

Tristar Pattern (Pattern Recognition)

Inputs:
    prices: ['open', 'high', 'low', 'close']
Outputs:
    integer (values are -100, 0 or 100)

I have not used these that much, but zero typically represents no-pattern, and positive and negative values represent that the pattern is observed at that point in the data.

It would be great to make a few test cases or examples showing a particular pattern and have it be detected by calling the relevant talib function!

greencoder commented 9 years ago

Thanks @mrjbq7 for your help with this. Through a bit of fumbling with this example, I was able to figure out it's expecting a numpy ndarray, though I'm not familiar with numpy and obviously have a lot to learn.

This is a good example of how the actual usage eludes the beginner and where examples would help a lot.

The candlestick pattern recognition functions seem to take the same inputs, so if I can figure it out for this one, I should be apple to apply it to all.

import talib
import numpy 

sample_data = [
  ['Mon', 20, 28, 38, 45],
  ['Tue', 31, 38, 39, 50],
  ['Wed', 50, 55, 56, 62],
  ['Thu', 77, 70, 71, 60],
  ['Fri', 68, 66, 22, 15],
 ]

 # Not sure how to turn my sample data into a ndarray
 my_ndarray = numpy.ndarray(?)

 talib.CDLTRISTAR(my_ndarray)

I realize this is a question better suited for Stack Overflow, and I'll bring further questions there. If anyone can help me construct the numpy.ndarray for this trivial little example, perhaps it will help someone in the future.

I'll be happy to create further examples for the wiki if I can figure this out!

mrjbq7 commented 9 years ago

Ahh, I see your issue has to do with how to deal with the open, high, low, close values.

So, numpy.ndarray works a bit like a list, except it's usually typed values (meaning a list of 64-bit floats, or 32-bit integers, etc.). You can either do:

1) Format the data initially the way talib expects:

import talib
import numpy

dates = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri']
open = [20, 31, 50, 77, 68]
high = [28, 38, 55, 70, 66]
low = [38, 39, 56, 71, 22]
close = [45, 50, 62, 60, 15]

# either start with numpy.ndarray, or convert to it like this
# (making sure to specify the ``dtype`` (or "data type") is
# 64-bit floating point which is what ``talib`` expects):
open = numpy.array(open, dtype=float)
high = numpy.array(high, dtype=float)
low = numpy.array(low, dtype=float)
close = numpy.array(close, dtype=float)

talib.CDLTRISTAR(open, high, low, close)

2) Take your data like it is (as rows of observations), which is often how data comes back from CSV files or from Yahoo! Finance, etc. and convert to columns of data.

import talib
import numpy

sample_data = [
  ['Mon', 20, 28, 38, 45],
  ['Tue', 31, 38, 39, 50],
  ['Wed', 50, 55, 56, 62],
  ['Thu', 77, 70, 71, 60],
  ['Fri', 68, 66, 22, 15],
 ]

# convert data to columns
sample_data = numpy.column_stack(sample_data)

# extract the columns we need, making sure to make them 64-bit floats
open = sample_data[1].astype(float)
high = sample_data[2].astype(float)
low = sample_data[3].astype(float)
close = sample_data[4].astype(float)

talib.CDLTRISTAR(open, high, low, close)

3) Other methods could include using pandas which has nice support for working with data.

import talib
import numpy
import pandas

sample_data = [
  ['Mon', 20, 28, 38, 45],
  ['Tue', 31, 38, 39, 50],
  ['Wed', 50, 55, 56, 62],
  ['Thu', 77, 70, 71, 60],
  ['Fri', 68, 66, 22, 15],
 ]

sample_data = pandas.DataFrame(sample_data,
                               columns=["Day","Open","High","Low","Close"])

open = sample_data['Open']
high = sample_data['High']
low = sample_data['Low']
close = sample_data['Close']

talib.CDLTRISTAR(open, high, low, close)

As an aside, it is fairly common to see people abbreviate when working with numpy and pandas, for example:

import numpy as np
np.array([1,2,3,4])

import pandas as pd
pd.DataFrame([[1,2],[3,4]])

I've even see people do the same with import talib as ta. I think thats maybe a bit much, but it does tend to make the code more readable when you are calling a lot of numpy functions. I've also seen used shorthand o, h, l, c for the open, high, low, close variables. It's mostly an aesthetic thing and there is no universal right answer so play around and see what works for you.

greencoder commented 9 years ago

@mrjbq7 First, thank you so much for taking the time to explain this so clearly. Your help is appreciated greatly.

I made a contrived example to test. I ran the number in Excel and produced a graph that looks like a Tristar pattern: http://cl.ly/image/3w1D0u1Y3O1O

Here's the code:

import talib
import numpy

sample_data = [
    ['1/22/14', 10, 18,  5, 20],
    ['1/23/14', 12, 21,  7, 22],
    ['1/24/14', 14, 24, 9 , 24],
    ['1/25/14', 16, 27, 11, 26],
    ['1/26/14', 18, 30, 13, 28],
    ['1/27/14', 20, 33, 15, 30],
    ['1/28/14', 22, 36, 17, 32],
    ['1/29/14', 24, 39, 19, 34],
    ['1/30/14', 26, 41, 21, 38],
    ['1/31/14', 30, 45, 25, 40],
    ['2/01/14', 43, 44, 42, 43],
    ['2/02/14', 46, 47, 45, 46],
    ['2/03/14', 44, 45, 43, 44],
    ['2/04/14', 40, 55, 35, 50],
]

# convert data to columns
sample_data = numpy.column_stack(sample_data)

# extract the columns we need, making sure to make them 64-bit floats
open = sample_data[1].astype(float)
high = sample_data[2].astype(float)
low = sample_data[3].astype(float)
close = sample_data[4].astype(float)

print talib.CDLTRISTAR(open, high, low, close)

The output is:

[   0    0    0    0    0    0    0    0    0    0    0    0 -100    0]

It looks like my sample data produced a result, though I'm not clear on what +100 vs -100 is?

pcawthron commented 9 years ago

@greencoder The -100 denotes a bearish Tristar pattern where the middle candle body is above the other two. Conversely +100 denotes a bullish Tristar pattern where the middle body is below the adjacent ones.

This is some TA-Lib source code from ta_CDLTRISTAR.c :

/* Proceed with the calculation for the requested range.
    * Must have:
    * - 3 consecutive doji days
    * - the second doji is a star
    * The meaning of "doji" is specified with TA_SetCandleSettings
    * outInteger is positive (1 to 100) when bullish or negative (-1 to -100) when bearish
    */
   i = startIdx;
   outIdx = 0;
   do
   {
        if( TA_REALBODY(i-2) <= TA_CANDLEAVERAGE( BodyDoji, BodyPeriodTotal, i-2 ) &&    // 1st: doji
            TA_REALBODY(i-1) <= TA_CANDLEAVERAGE( BodyDoji, BodyPeriodTotal, i-2 ) &&    // 2nd: doji
            TA_REALBODY(i) <= TA_CANDLEAVERAGE( BodyDoji, BodyPeriodTotal, i-2 ) ) {     // 3rd: doji
            outInteger[outIdx] = 0;
            if ( TA_REALBODYGAPUP(i-1,i-2)                                                  // 2nd gaps up
                 &&
                 max(inOpen[i],inClose[i]) < max(inOpen[i-1],inClose[i-1])                  // 3rd is not higher than 2nd
               )
                outInteger[outIdx] = -100;
            if ( TA_REALBODYGAPDOWN(i-1,i-2)                                                // 2nd gaps down
                 &&
                 min(inOpen[i],inClose[i]) > min(inOpen[i-1],inClose[i-1])                  // 3rd is not lower than 2nd
               )
                outInteger[outIdx] = +100;
            outIdx++;
        }
        else
            outInteger[outIdx++] = 0;
        /* add the current range and subtract the first range: this is done after the pattern recognition 
         * when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
         */
        BodyPeriodTotal += TA_CANDLERANGE( BodyDoji, i-2 ) - TA_CANDLERANGE( BodyDoji, BodyTrailingIdx );
        i++;
        BodyTrailingIdx++;
   } while( i <= endIdx );
greencoder commented 9 years ago

Thanks, @pcawthron! In general, are negative values bearish and positive values bullish for the candlestick recognition functions?

pcawthron commented 9 years ago

@greencoder As far as I know, yes, but it's best to check the source code. In my limited experience I've only ever seen -100, 0 and +100 so I'm not sure why the source talks of -1 to -100 and +1 to +100.

greencoder commented 9 years ago

@mrjbq7 I'm trying to create a few samples we can use for showing people how to use the pattern recognition functions as you and @pcawthron taught me above.

Given this program:

import talib
import numpy

original_data = [
    ['1/22/14', 10, 18,  5, 20],
    ['1/23/14', 12, 21,  7, 22],
    ['1/24/14', 14, 24, 9 , 24],
    ['1/25/14', 16, 27, 11, 26],
    ['1/26/14', 18, 30, 13, 28],
    ['1/27/14', 20, 33, 15, 30],
    ['1/28/14', 22, 36, 17, 32],
    ['1/29/14', 24, 39, 19, 34],
    ['1/30/14', 26, 41, 21, 38],
    ['1/31/14', 30, 45, 25, 40],
    ['2/01/14', 43, 44, 42, 43],
    ['2/02/14', 46, 47, 45, 46],
    ['2/03/14', 44, 45, 43, 44],
    ['2/04/14', 40, 55, 35, 50],
]

# convert data to columns
columnar_data = numpy.column_stack(original_data)

# extract the columns we need, making sure to make them 64-bit floats
dates = columnar_data[0].astype(str)
open = columnar_data[1].astype(float)
high = columnar_data[2].astype(float)
low = columnar_data[3].astype(float)
close = columnar_data[4].astype(float)

result = talib.CDLTRISTAR(open, high, low, close)
print result

It produces this output:

[   0    0    0    0    0    0    0    0    0    0    0    0 -100    0]

This is the first time I've ever worked with Numpy and I'd like to make sure that how I'm using the result is correct and elegant.

To identify the day in the result, I'm doing this:

if -100 in values:
    result_index = values.tolist().index(-100)
    print "Identified bearish Tristar pattern at %s" % original_data[result_index][0]

This works, but I'm not sure if there is a more elegant way to do this. (there probably is)

Specifically:

  1. Is there a better way to find non-zero values in a numpy array than to convert it to a Python list?
  2. If so, perhaps I could correlate it to a value in the dates Numpy array I created?

Once I get this worked out, I'd like to put an example using Yahoo data in the project wiki.

mrjbq7 commented 9 years ago

Regarding your question, non-zero values can be found several ways.

In [1]: import numpy as np

In [2]: a = np.array([0,0,100,-100,0,0])

In [3]: np.nonzero(a)
Out[3]: (array([2, 3]),)

In [4]: np.where(a != 0)
Out[4]: (array([2, 3]),)
hasakura511 commented 8 years ago

mrjbq7,

thank you for the ta-lib contribution. For the CDLHIKKAKE function, I am getting some 200 & -200 output on my price series.

test = ta.CDLHIKKAKE(open,high,low,close)

for x in test.nonzero(): print test[x]

[ 100 200 -100 -200 -100 -100 -200 -100 100 200 100 -100 100 -100 -200...

according to the help, it says 200/-200 is not an valid output.

Docstring: CDLHIKKAKE(open, high, low, close)

Hikkake Pattern (Pattern Recognition)

Inputs: prices: ['open', 'high', 'low', 'close'] Outputs: integer (values are -100, 0 or 100) Type: builtin_function_or_method

Should I assume that -200/200 to be 100's?

Thank you

mrjbq7 commented 8 years ago

200/-200 is a little strange. I'd have to look at the underling libta_lib library code to see what it is doing...

exquest commented 8 years ago

How do you access the documentation for each function?

mrjbq7 commented 8 years ago

What documentation are you looking for?

You can look at general documentation for various indicators: http://tadoc.org/.

You could also look at the underlying C source code of ta-lib: https://sourceforge.net/p/ta-lib/code/HEAD/tree/trunk/ta-lib/c/src/ta_func/

etc.

exquest commented 8 years ago

I was looking for the python function documentation. I found it here:

https://mrjbq7.github.io/ta-lib/funcs.html

Thanks

mrjbq7 commented 8 years ago

You can also use help from the Python console to see what arguments a function takes and its default values.

neerajgupta2407 commented 7 years ago

@mrjbq7 HI, I want to validate the results. Now for sampling, i am feeding the dummy data for MARUBOZU pattern which is very simple but still function is returning as 0. Please explain what i am missing??

Sample Data:
    # open, high, low, close
    [10,20,10,20]

import talib
import numpy

sample_data = [
    # open, high, low, close
    [10,20,10,20]
]
sample_data = numpy.column_stack(sample_data)
open = sample_data[0].astype(float)
high = sample_data[1].astype(float)
low = sample_data[2].astype(float)
close = sample_data[3].astype(float)

talib.CDLMARUBOZU(open, high, low, close)

It is returning array([0], dtype=int32), whereas data feeded is for pattern MARUBOZU. How can i verify the results ??

KabeerSinghBedi commented 7 years ago

@mrjbq7 the issue with the talib-Pattern recognition is determining more than one candlestick type for a single type of ohlc value. Is their any way to solve this issue?? Can u please help image

mrjbq7 commented 7 years ago

I don't understand the problem you are having @KabeerSinghBedi.

mrjbq7 commented 7 years ago

@neerajgupta2407 The pattern might not trigger because all the candle open=high=low=close and maybe it needs candle bodies or something to trigger. You can look at the code for the C library and see what logic it uses.

KabeerSinghBedi commented 7 years ago

@mrjbq7 as u can see in the image for a particular set of Ohlc it should determine it as single candle stick type but it is determining more than one type for in my case it's highwave and spinning top. image

mrjbq7 commented 7 years ago

Why can't multiple candlestick patterns trigger on the same tick of the market?

KabeerSinghBedi commented 7 years ago

But in that case each candle stick has a different meaning so how can at a particular tick we can have different meanings.

On Jun 30, 2017 11:31 AM, "John Benediktsson" notifications@github.com wrote:

Why can't multiple candlestick patterns trigger on the same tick of the market?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/mrjbq7/ta-lib/issues/74#issuecomment-312182830, or mute the thread https://github.com/notifications/unsubscribe-auth/AZFxqan6Jpi-k5iCuyB--JbB-UbNVEbSks5sJI9IgaJpZM4DVhUe .

KabeerSinghBedi commented 7 years ago

But in that case each candle stick has a different meaning so how can at a particular tick we can have different meanings.

KabeerSinghBedi commented 7 years ago

If i'm making changes in the ta_global.c file how to see that this changes are because if i'm changing the candle settings i'm not able to see the changes in pattern recognition method.

mrjbq7 commented 7 years ago

I don't see why more than one candlestick pattern might be recognized on the addition of a new candle. Are the two you observed inconsistent?

What changes are you making to ta_global.c? That's not something I can help you troubleshoot without access to what you are doing and not likely to have time to do so.

MattinAhmed commented 7 years ago

Hi.. Could someone please let me know about detecting candlestick patterns To detect a candle-stick pattern in the stock data, do I need to have my data in my numpy array in ascending order with respect to dates(oldest to newest dates) or the other way round.

for example lets say my date is sample_data = [ ['2/5/2012', 20, 28, 38, 45], ['3/5/2012', 31, 38, 39, 50], ['4/5/2012', 50, 55, 56, 62], ['5/5/2012', 77, 70, 71, 60], ['6/5/2012', 68, 66, 22, 15], ]

convert data to columns

sample_data = numpy.column_stack(sample_data)

extract the columns we need, making sure to make them 64-bit floats

open = sample_data[1].astype(float) high = sample_data[2].astype(float) low = sample_data[3].astype(float) close = sample_data[4].astype(float)

talib.CDLTRISTAR(open, high, low, close)

OR Should i have my data in form of date from newest to oldest like this sample_data = [ ['6/5/2012', 20, 28, 38, 45], ['5/5/2012', 31, 38, 39, 50], ['4/5/2012', 50, 55, 56, 62], ['3/5/2012', 77, 70, 71, 60], ['2/5/2012', 68, 66, 22, 15], ]

Please advice.. Thanks

mrjbq7 commented 7 years ago

Typical time series arrays are oldest to newest.

pcawthron commented 7 years ago

Here's an example that uses CDLHAMMER:

from matplotlib.finance import candlestick2_ohlc
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
import datetime as datetime
import numpy as np
import talib

quotes = np.array([ (1459388100, 29.799999237060547, 29.799999237060547, 29.799999237060547, 29.799999237060547, 148929.0, 450030016.0),
   (1459388400, 29.799999237060547, 29.979999542236328, 29.709999084472656, 29.920000076293945, 10395.0, 31069984.0),
   (1459388700, 29.959999084472656, 30.18000030517578, 29.719999313354492, 30.149999618530273, 38522.0, 114999968.0),
   (1459389000, 30.170000076293945, 30.479999542236328, 30.0, 30.149999618530273, 29823.0, 90220032.0),
   (1459389300, 30.149999618530273, 30.75, 30.1299991607666, 30.549999237060547, 38903.0, 118620032.0),
   (1459389600, 30.59000015258789, 30.93000030517578, 30.559999465942383, 30.65999984741211, 42308.0, 130000000.0),
   (1459389900, 30.6200008392334, 30.690000534057617, 30.3799991607666, 30.3799991607666, 20209.0, 61689984.0),
   (1459390200, 30.3700008392334, 30.489999771118164, 30.18000030517578, 30.18000030517578, 18491.0, 56169984.0),
   (1459390500, 30.190000534057617, 30.329999923706055, 30.010000228881836, 30.010000228881836, 17641.0, 53200000.0),
   (1459390800, 30.030000686645508, 30.399999618530273, 30.030000686645508, 30.280000686645508, 9526.0, 28899968.0),
   (1459391100, 30.299999237060547, 30.31999969482422, 30.200000762939453, 30.209999084472656, 9282.0, 28100096.0),
   (1459391400, 30.190000534057617, 30.280000686645508, 30.049999237060547, 30.1200008392334, 8663.0, 26099968.0),
   (1459391700, 30.110000610351562, 30.110000610351562, 29.959999084472656, 30.100000381469727, 15677.0, 47099904.0),
   (1459392000, 30.1200008392334, 30.260000228881836, 30.0, 30.059999465942383, 5649.0, 17000064.0),
   (1459392300, 30.079999923706055, 30.299999237060547, 30.0, 30.280000686645508, 6057.0, 18199936.0),
   (1459392600, 30.290000915527344, 30.34000015258789, 30.1200008392334, 30.1200008392334, 7914.0, 24000000.0),
   (1459392900, 30.1299991607666, 30.15999984741211, 30.079999923706055, 30.139999389648438, 4521.0, 13600000.0),
   (1459393200, 30.139999389648438, 30.139999389648438, 29.829999923706055, 29.899999618530273, 16255.0, 48600064.0),
   (1459393500, 29.93000030517578, 30.1200008392334, 29.889999389648438, 30.1200008392334, 6877.0, 20600064.0),
   (1459393800, 30.1299991607666, 30.15999984741211, 29.979999542236328, 30.030000686645508, 3803.0, 11499904.0),
   (1459394100, 30.040000915527344, 30.1299991607666, 30.0, 30.030000686645508, 4421.0, 13300096.0),
   (1459394400, 29.989999771118164, 30.389999389648438, 29.989999771118164, 30.389999389648438, 7011.0, 21099904.0),
   (1459394700, 30.399999618530273, 30.450000762939453, 30.270000457763672, 30.299999237060547, 12095.0, 36800000.0),
   (1459395000, 30.34000015258789, 30.450000762939453, 30.280000686645508, 30.43000030517578, 9284.0, 28099968.0),
   (1459400700, 30.510000228881836, 30.729999542236328, 30.5, 30.600000381469727, 17139.0, 52500096.0),
   (1459401000, 30.600000381469727, 30.799999237060547, 30.530000686645508, 30.790000915527344, 11888.0, 36400000.0),
   (1459401300, 30.809999465942383, 31.100000381469727, 30.809999465942383, 31.049999237060547, 30692.0, 95099904.0),
   (1459401600, 31.06999969482422, 31.559999465942383, 30.93000030517578, 31.559999465942383, 24473.0, 76200064.0),
   (1459401900, 31.600000381469727, 31.860000610351562, 31.299999237060547, 31.450000762939453, 34497.0, 109200000.0),
   (1459402200, 31.43000030517578, 31.600000381469727, 31.18000030517578, 31.18000030517578, 18525.0, 58200064.0),
   (1459402500, 31.18000030517578, 31.350000381469727, 31.040000915527344, 31.18000030517578, 10153.0, 31599872.0),
   (1459402800, 31.200000762939453, 31.399999618530273, 31.010000228881836, 31.389999389648438, 9668.0, 30100096.0),
   (1459403100, 31.399999618530273, 31.399999618530273, 31.110000610351562, 31.360000610351562, 8445.0, 26499968.0),
   (1459403400, 31.360000610351562, 31.399999618530273, 31.040000915527344, 31.100000381469727, 9538.0, 29799936.0),
   (1459403700, 31.1200008392334, 31.399999618530273, 31.100000381469727, 31.270000457763672, 7996.0, 25000064.0),
   (1459404000, 31.270000457763672, 31.399999618530273, 31.15999984741211, 31.399999618530273, 6760.0, 21100032.0),
   (1459404300, 31.389999389648438, 32.400001525878906, 31.389999389648438, 32.189998626708984, 26108.0, 83700096.0),
   (1459404600, 32.209999084472656, 32.400001525878906, 31.860000610351562, 32.29999923706055, 15736.0, 50599936.0),
   (1459404900, 32.29999923706055, 32.310001373291016, 31.489999771118164, 31.489999771118164, 12945.0, 41399808.0),
   (1459405200, 31.5, 32.0, 31.40999984741211, 31.81999969482422, 11901.0, 37700096.0),
   (1459405500, 31.809999465942383, 31.940000534057617, 31.719999313354492, 31.770000457763672, 6503.0, 20700160.0),
   (1459405800, 31.760000228881836, 31.790000915527344, 31.399999618530273, 31.790000915527344, 10103.0, 31899904.0),
   (1459406100, 31.780000686645508, 32.029998779296875, 31.780000686645508, 31.850000381469727, 12033.0, 38500096.0),
   (1459406400, 31.809999465942383, 33.310001373291016, 31.809999465942383, 33.029998779296875, 58238.0, 192199936.0),
   (1459406700, 33.029998779296875, 33.310001373291016, 32.79999923706055, 32.79999923706055, 36689.0, 121900032.0),
   (1459407000, 32.79999923706055, 32.869998931884766, 32.61000061035156, 32.70000076293945, 15245.0, 49799936.0),
   (1459407300, 32.68000030517578, 32.689998626708984, 31.799999237060547, 32.0099983215332, 20507.0, 65999872.0),
   (1459407600, 32.02000045776367, 32.02000045776367, 31.760000228881836, 31.799999237060547, 29610.0, 94300160.0)],
   dtype=[('time', '<i4'), ('open', 'd'), ('high', 'd'), ('low', 'd'), ('close', 'd'), ('volume', 'd'), ('amount', 'd')])

fig, ax = plt.subplots()
candlestick2_ohlc(ax,quotes['open'],quotes['high'],quotes['low'],quotes['close'],width=0.6)

xdate = [datetime.datetime.fromtimestamp(i) for i in quotes['time']]

ax.xaxis.set_major_locator(ticker.MaxNLocator(6))

def mydate(x,pos):
    try:
        return xdate[int(x)]
    except IndexError:
        return ''

ax.xaxis.set_major_formatter(ticker.FuncFormatter(mydate))

fig.autofmt_xdate()
fig.tight_layout()

plt.show()

o, h, l, c = np.double(quotes['open']), np.double(quotes['high']), np.double(quotes['low']), np.double(quotes['close'])
talib.CDLHAMMER(o,h,l,c)

CDHAMMER Demo

metashock commented 6 years ago

@mrjbq7 Any news about the 200/-200 issue? Following the documentation this should not happen. (including the inline documentation of the C code)

mrjbq7 commented 6 years ago

What is the issue?

And what documentation are you talking about?

This is in ta_CDLHIKKAKE.c:

https://svn.code.sf.net/p/ta-lib/code/trunk/ta-lib/c/src/ta_func/ta_CDLHIKKAKE.c

/* Generated */             if( i <= patternIdx+3 &&
/* Generated */                 ( ( patternResult > 0 && inClose[i] > inHigh[patternIdx-1] )    // close higher than the high of 2nd
/* Generated */                   ||
/* Generated */                   ( patternResult < 0 && inClose[i] < inLow[patternIdx-1] )     // close lower than the low of 2nd
/* Generated */                 )
/* Generated */             ) {
/* Generated */                 outInteger[outIdx++] = patternResult + 100 * ( patternResult > 0 ? 1 : -1 );
/* Generated */                 patternIdx = 0;
/* Generated */             } else
/* Generated */                 outInteger[outIdx++] = 0;

That implies that the patternResult is doubled if a confirmation candle is observed. So you can probably treat a 200 either a "100" or handle that case specially in your code.

I'm not sure there is anything to do here...

metashock commented 6 years ago

Well, I'm not familiar with the talib C code so far and honestly, it is hard to read. But if you say so...

Btw, I'm referring to this piece of inline documentation:

   /* Proceed with the calculation for the requested range.
    * Must have:
    * - first and second candle: inside bar (2nd has lower high and higher low than 1st)
    * - third candle: lower high and lower low than 2nd (higher high and higher low than 2nd)
    * outInteger[hikkakebar] is positive (1 to 100) or negative (-1 to -100) meaning bullish or bearish hikkake
    * Confirmation could come in the next 3 days with:
    * - a day that closes higher than the high (lower than the low) of the 2nd candle
    * outInteger[confirmationbar] is equal to 100 + the bullish hikkake result or -100 - the bearish hikkake result
    * Note: if confirmation and a new hikkake come at the same bar, only the new hikkake is reported (the new hikkake
    * overwrites the confirmation of the old hikkake)
    */

But it looks like this applies only to the block below it. This 200 magic happens at the bottom, in an undocumented, generated block. Goodbye readability!


PS: I guess the key here is to do the math once manually to understand it. Then the C code becomes more readable. Anyhow, I was just playing around a bit.

Thanks for your help!

mrjbq7 commented 6 years ago

I think the 200 comes from this "confirmation" line in the documentation:

outInteger[confirmationbar] is equal to 100 + the bullish hikkake result

Assuming the bullish hikkake result is in the range [1,100] then that confirmation bar is in the range [101,200].

mrjbq7 commented 6 years ago

Also, I don't mind at all the questions. I learn something usually every time someone tries to figure out how the TA-Lib C library works!

xiaxio commented 6 years ago

Thanks @pcawthron for your code. I always learn best with example code. Of course thanks to @mrjbq7 for all your hard work on ta-lib. If you are reading this and tried @pcawthron code, you will notice that matplotlib has deprecated the finance module since version 2.2. You will find the solution here: https://stackoverflow.com/questions/42373104/since-matplotlib-finance-has-been-deprecated-how-can-i-use-the-new-mpl-finance Best regards