TA-Lib / ta-lib-python

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

Candlesticks pattern recognition 0.4.10 is incorrect #119

Open bkcollection opened 7 years ago

bkcollection commented 7 years ago

I found that CDLHAMMER,CDLDOJI and CDLSHOOTINGSTAR are incorrect. This is data for KESM, A stock from KLSE Malaysia.

Date,Stock,Open,High,Low,Close,Volume
2016-09-29,KESM,7.92,7.98,7.92,7.97,149400
2016-09-30,KESM,7.96,7.97,7.84,7.9,29900
2016-10-04,KESM,7.8,7.94,7.8,7.93,99900
2016-10-05,KESM,7.93,7.95,7.89,7.93,77500
2016-10-06,KESM,7.93,7.93,7.89,7.92,130600
2016-10-07,KESM,7.91,7.94,7.91,7.92,103000

ta.CDLHAMMER(o,h,l,c) and I got a 100 signal. I am using python, pandas web.datareader to grab data from google(this is a Malaysia stock, so put KLSE: to grab the data) It CDLHAMMER shows that there is a hammer signal on Oct 07. This is incorrect. It is more look like shooting star more but shooting star must be in a uptrend. First, this is not a downtrend for fulfil hammer characteristic. the wicks is below the body. Second, the wicks must be at least 2 times the body (white or black) This KESM, does not in downtrend. It also open and close at the same price. The wicks is above the body. This is not the only case, it is just an example from many cases.

ta.CDLSHOOTINGSTAR(o,h,l,c) for another two stocks also incorrect. Shooting star definition:

  1. happen in uptrend
  2. wicks is 2 times body where wicks is above the body(white or black)
2016-09-30,PBBANK,19.86,20.0,19.78,19.82,8007100
2016-10-04,PBBANK,19.92,19.92,19.82,19.88,5551100
2016-10-05,PBBANK,19.96,19.96,19.84,19.92,7949300
2016-10-06,PBBANK,19.96,19.98,19.9,19.96,5000900
2016-10-07,PBBANK,19.96,19.96,19.86,19.88,5598000
2016-09-28,MFLOUR,1.52,1.53,1.49,1.5,274600
2016-09-29,MFLOUR,1.5,1.52,1.5,1.52,52400
2016-09-30,MFLOUR,1.5,1.5,1.49,1.49,111000
2016-10-04,MFLOUR,1.49,1.5,1.48,1.48,220900
2016-10-05,MFLOUR,1.48,1.5,1.48,1.48,45200
2016-10-06,MFLOUR,1.48,1.49,1.46,1.48,163300
2016-10-07,MFLOUR,1.48,1.48,1.42,1.42,643800

MFLOUR is in downtrend, and it has a long black body with no wicks, it is not a shooting star. PBBANK is sideway, and also look like a hammer as the wicks is below the body.

Is t something I implement wrongly or the candlectisls pattern recognition really inaccurate? I check on RIS,MACD all the data looks correct.

mrjbq7 commented 7 years ago

I wonder if we can try different CandleSettings and see if that makes it work:

https://github.com/mrjbq7/ta-lib/blob/master/talib/libta_lib.pxd#L73

Or maybe there is a bug in the underlying C library.

bkcollection commented 7 years ago

Hi Thanks for reply. In this case, you mean I should modified the setting myself? I am not good in C as I only use Python. What cahnges I need to made? Or I need to wait the next update of Talib library? By the way, I feel something is reversed. Shooting star detected more like Hammer while Hammer detected like Shooting star. What do you think?

On Tue, Oct 11, 2016 at 10:34 PM, John Benediktsson < notifications@github.com> wrote:

I wonder if we can try different CandleSettings and see if that makes it work:

https://github.com/mrjbq7/ta-lib/blob/master/talib/libta_lib.pxd#L73

Or maybe there is a bug in the underlying C library.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/mrjbq7/ta-lib/issues/119#issuecomment-252935184, or mute the thread https://github.com/notifications/unsubscribe-auth/ARtuA-wt0LSp-WZfxSULFBGuPYC6GM2Cks5qy56NgaJpZM4KSMpy .

mrjbq7 commented 7 years ago

Can you paste your test case and I'll try it with different candlestick settings to see if it makes a difference?

bkcollection commented 7 years ago

What is test case you refer to? it is the candlestick settings or my python code? will try my best to give supportive data to you. On Oct 12, 2016 12:40 AM, "John Benediktsson" notifications@github.com wrote:

Can you paste your test case and I'll try it with different candlestick settings to see if it makes a difference?

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/mrjbq7/ta-lib/issues/119#issuecomment-252972946, or mute the thread https://github.com/notifications/unsubscribe-auth/ARtuA3HNi2w95o2Y7-CFtZyvHVOFGh0Uks5qy7wQgaJpZM4KSMpy .

femtotrader commented 7 years ago

I think what @mrjbq7 is looking for is

Here is an example code that you can complete

import pandas as pd
from pandas.compat import StringIO

import matplotlib.pyplot as plt
from matplotlib.finance import candlestick_ohlc
import matplotlib.dates as mdates

def plot_candlestick(df, ax=None):
    if ax is None:
        fig, ax = plt.subplots()
    idx_name = df.index.name
    dat = df.reset_index()[[idx_name, "Open", "High", "Low", "Close"]]
    dat[df.index.name] = dat[df.index.name].map(mdates.date2num)
    ax.xaxis_date()
    ax.xaxis.set_major_formatter(mdates.DateFormatter("%Y-%m-%d"))
    plt.xticks(rotation=45)
    _ = candlestick_ohlc(ax, dat.values, width=.6, colorup='g', alpha=1)
    ax.set_xlabel(idx_name)
    ax.set_ylabel("OHLC")
    return ax

data="""Date,Stock,Open,High,Low,Close,Volume
2016-09-29,KESM,7.92,7.98,7.92,7.97,149400
2016-09-30,KESM,7.96,7.97,7.84,7.9,29900
2016-10-04,KESM,7.8,7.94,7.8,7.93,99900
2016-10-05,KESM,7.93,7.95,7.89,7.93,77500
2016-10-06,KESM,7.93,7.93,7.89,7.92,130600
2016-10-07,KESM,7.91,7.94,7.91,7.92,103000"""
df = pd.read_csv(StringIO(data), index_col='Date', parse_dates=True)
o = df["Open"].values
h = df["High"].values
l = df["Low"].values
c = df["Close"].values

ax = plot_candlestick(df)

print(ax)

plt.tight_layout()
plt.savefig("candle.png")
plt.show()

Some screenshots also help.

candle

If you do this I could also have a look and compare with my Julia TALib wrapper https://github.com/femtotrader/TALib.jl

bkcollection commented 7 years ago

My python code which included all candlesticks patterns

import pandas as pd
import numpy as np
import os.path
import talib as ta
from pandas_datareader import data as web
import os

start = datetime.datetime(2015, 1, 1)
now = datetime.datetime.now()

KLSEData = ['KESM','MFLOUR','PBBANK']
KLSElen = len(KLSEData)

df_2CROWS = pd.DataFrame(columns=['Stock','2CROWS'])
df_3BLACKCROWS = pd.DataFrame(columns=['Stock','3BLACKCROWS'])
df_3INSIDE = pd.DataFrame(columns=['Stock','3INSIDE'])
df_3LINESTRIKE = pd.DataFrame(columns=['Stock','3LINESTRIKE'])
df_3OUTSIDE = pd.DataFrame(columns=['Stock','3OUTSIDE'])
df_3STARSINSOUTH = pd.DataFrame(columns=['Stock','3STARSINSOUTH'])
df_3WHITESOLDIERS = pd.DataFrame(columns=['Stock','3WHITESOLDIERS'])
df_ABANDONEDBABY = pd.DataFrame(columns=['Stock','ABANDONEDBABY'])
df_ADVANCEBLOCK = pd.DataFrame(columns=['Stock','ADVANCEBLOCK'])
df_BELTHOLD = pd.DataFrame(columns=['Stock','BELTHOLD'])
df_BREAKAWAY = pd.DataFrame(columns=['Stock','BREAKAWAY'])
df_CLOSINGMARUBOZU = pd.DataFrame(columns=['Stock','CLOSINGMARUBOZU'])
df_CONCEALBABYSWALL = pd.DataFrame(columns=['Stock','CONCEALBABYSWALL'])
df_COUNTERATTACK = pd.DataFrame(columns=['Stock','COUNTERATTACK'])
df_DARKCLOUDCOVER = pd.DataFrame(columns=['Stock','DARKCLOUDCOVER'])
df_DOJI = pd.DataFrame(columns=['Stock','DOJI'])
df_DOJISTAR = pd.DataFrame(columns=['Stock','DOJISTAR'])
df_DRAGONFLYDOJI = pd.DataFrame(columns=['Stock','DRAGONFLYDOJI'])
df_ENGULFING = pd.DataFrame(columns=['Stock','ENGULFING'])
df_EVENINGDOJISTAR = pd.DataFrame(columns=['Stock','EVENINGDOJISTAR'])
df_EVENINGSTAR = pd.DataFrame(columns=['Stock','EVENINGSTAR'])
df_GAPSIDESIDEWHITE = pd.DataFrame(columns=['Stock','GAPSIDESIDEWHITE'])
df_GRAVESTONEDOJI = pd.DataFrame(columns=['Stock','GRAVESTONEDOJI'])
df_HAMMER = pd.DataFrame(columns=['Stock','HAMMER'])
df_HANGINGMAN = pd.DataFrame(columns=['Stock','HANGINGMAN'])
df_HARAMI = pd.DataFrame(columns=['Stock','HARAMI'])
df_HARAMICROSS = pd.DataFrame(columns=['Stock','HARAMICROSS'])
df_HIGHWAVE = pd.DataFrame(columns=['Stock','HIGHWAVE'])
df_HIKKAKE = pd.DataFrame(columns=['Stock','HIKKAKE'])
df_HIKKAKEMOD = pd.DataFrame(columns=['Stock','HIKKAKEMOD'])
df_HOMINGPIGEON = pd.DataFrame(columns=['Stock','HOMINGPIGEON'])
df_IDENTICAL3CROWS = pd.DataFrame(columns=['Stock','IDENTICAL3CROWS'])
df_INNECK = pd.DataFrame(columns=['Stock','INNECK'])
df_INVERTEDHAMMER = pd.DataFrame(columns=['Stock','INVERTEDHAMMER'])
df_KICKING = pd.DataFrame(columns=['Stock','KICKING'])
df_KICKINGBYLENGTH = pd.DataFrame(columns=['Stock','KICKINGBYLENGTH'])
df_LADDERBOTTOM = pd.DataFrame(columns=['Stock','LADDERBOTTOM'])
df_LONGLEGGEDDOJI = pd.DataFrame(columns=['Stock','LONGLEGGEDDOJI'])
df_LONGLINE = pd.DataFrame(columns=['Stock','LONGLINE'])
df_MARUBOZU = pd.DataFrame(columns=['Stock','MARUBOZU'])
df_MATCHINGLOW = pd.DataFrame(columns=['Stock','MATCHINGLOW'])
df_MATHOLD = pd.DataFrame(columns=['Stock','MATHOLD'])
df_MORNINGDOJISTAR = pd.DataFrame(columns=['Stock','MORNINGDOJISTAR'])
df_MORNINGSTAR = pd.DataFrame(columns=['Stock','MORNINGSTAR'])
df_ONNECK = pd.DataFrame(columns=['Stock','ONNECK'])
df_PIERCING = pd.DataFrame(columns=['Stock','PIERCING'])
df_RICKSHAWMAN = pd.DataFrame(columns=['Stock','RICKSHAWMAN'])
df_RISEFALL3METHODS = pd.DataFrame(columns=['Stock','RISEFALL3METHODS'])
df_SEPARATINGLINES = pd.DataFrame(columns=['Stock','SEPARATINGLINES'])
df_SHOOTINGSTAR = pd.DataFrame(columns=['Stock','SHOOTINGSTAR'])
df_SHORTLINE = pd.DataFrame(columns=['Stock','SHORTLINE'])
df_SPINNINGTOP = pd.DataFrame(columns=['Stock','SPINNINGTOP'])
df_STALLEDPATTERN = pd.DataFrame(columns=['Stock','STALLEDPATTERN'])
df_STICKSANDWICH = pd.DataFrame(columns=['Stock','STICKSANDWICH'])
df_TAKURI = pd.DataFrame(columns=['Stock','TAKURI'])
df_TASUKIGAP = pd.DataFrame(columns=['Stock','TASUKIGAP'])
df_THRUSTING = pd.DataFrame(columns=['Stock','THRUSTING'])
df_TRISTAR = pd.DataFrame(columns=['Stock','TRISTAR'])
df_UNIQUE3RIVER = pd.DataFrame(columns=['Stock','UNIQUE3RIVER'])
df_UPSIDEGAP2CROWS = pd.DataFrame(columns=['Stock','UPSIDEGAP2CROWS'])
df_XSIDEGAP3METHODS = pd.DataFrame(columns=['Stock','XSIDEGAP3METHODS'])
df_candle = pd.DataFrame(columns=['Stock','candle'])

for x in range (len(KLSEData)):
    print "###############  "
    print KLSEData [x]
    print "###############"
    try:
        q_data = pd.read_csv(KLSEData [x]+".csv", index_col='Stock')
    except Exception:
        continue

    high = q_data.High
    h=np.array(high)

    open_ = q_data.Open
    o = np.array(open_)

    low = q_data.Low
    l = np.array(low)

    close = q_data.Close
    c = np.array(close)

    vol = q_data.Volume
    v = np.array(vol)

    c_2CROWS = ta.CDL2CROWS(o,h,l,c)
    c_3BLACKCROWS = ta.CDL3BLACKCROWS(o,h,l,c)
    c_3INSIDE = ta.CDL3INSIDE(o,h,l,c)
    c_3LINESTRIKE = ta.CDL3LINESTRIKE(o,h,l,c)
    c_3OUTSIDE = ta.CDL3OUTSIDE(o,h,l,c)
    c_3STARSINSOUTH = ta.CDL3STARSINSOUTH(o,h,l,c)
    c_3WHITESOLDIERS = ta.CDL3WHITESOLDIERS(o,h,l,c)
    c_ABANDONEDBABY = ta.CDLABANDONEDBABY(o,h,l,c)
    c_ADVANCEBLOCK = ta.CDLADVANCEBLOCK(o,h,l,c)
    c_BELTHOLD = ta.CDLBELTHOLD(o,h,l,c)
    c_BREAKAWAY = ta.CDLBREAKAWAY(o,h,l,c)
    c_CLOSINGMARUBOZU = ta.CDLCLOSINGMARUBOZU(o,h,l,c)
    c_CONCEALBABYSWALL = ta.CDLCONCEALBABYSWALL(o,h,l,c)
    c_COUNTERATTACK = ta.CDLCOUNTERATTACK(o,h,l,c)
    c_DARKCLOUDCOVER = ta.CDLDARKCLOUDCOVER(o,h,l,c)
    c_DOJI = ta.CDLDOJI(o,h,l,c)
    c_DOJISTAR = ta.CDLDOJISTAR(o,h,l,c)
    c_DRAGONFLYDOJI = ta.CDLDRAGONFLYDOJI(o,h,l,c)
    c_ENGULFING = ta.CDLENGULFING(o,h,l,c)
    c_EVENINGDOJISTAR = ta.CDLEVENINGDOJISTAR(o,h,l,c)
    c_EVENINGSTAR = ta.CDLEVENINGSTAR(o,h,l,c)
    c_GAPSIDESIDEWHITE = ta.CDLGAPSIDESIDEWHITE(o,h,l,c)
    c_GRAVESTONEDOJI = ta.CDLGRAVESTONEDOJI(o,h,l,c)
    c_HAMMER = ta.CDLHAMMER(o,h,l,c)
    c_HANGINGMAN = ta.CDLHANGINGMAN(o,h,l,c)
    c_HARAMI = ta.CDLHARAMI(o,h,l,c)
    c_HARAMICROSS = ta.CDLHARAMICROSS(o,h,l,c)
    c_HIGHWAVE = ta.CDLHIGHWAVE(o,h,l,c)
    c_HIKKAKE = ta.CDLHIKKAKE(o,h,l,c)
    c_HIKKAKEMOD = ta.CDLHIKKAKEMOD(o,h,l,c)
    c_HOMINGPIGEON = ta.CDLHOMINGPIGEON(o,h,l,c)
    c_IDENTICAL3CROWS = ta.CDLIDENTICAL3CROWS(o,h,l,c)
    c_INNECK = ta.CDLINNECK(o,h,l,c)
    c_INVERTEDHAMMER = ta.CDLINVERTEDHAMMER(o,h,l,c)
    c_KICKING = ta.CDLKICKING(o,h,l,c)
    c_KICKINGBYLENGTH = ta.CDLKICKINGBYLENGTH(o,h,l,c)
    c_LADDERBOTTOM = ta.CDLLADDERBOTTOM(o,h,l,c)
    c_LONGLEGGEDDOJI = ta.CDLLONGLEGGEDDOJI(o,h,l,c)
    c_LONGLINE = ta.CDLLONGLINE(o,h,l,c)
    c_MARUBOZU = ta.CDLMARUBOZU(o,h,l,c)
    c_MATCHINGLOW = ta.CDLMATCHINGLOW(o,h,l,c)
    c_MATHOLD = ta.CDLMATHOLD(o,h,l,c)
    c_MORNINGDOJISTAR = ta.CDLMORNINGDOJISTAR(o,h,l,c)
    c_MORNINGSTAR = ta.CDLMORNINGSTAR(o,h,l,c)
    c_ONNECK = ta.CDLONNECK(o,h,l,c)
    c_PIERCING = ta.CDLPIERCING(o,h,l,c)
    c_RICKSHAWMAN = ta.CDLRICKSHAWMAN(o,h,l,c)
    c_RISEFALL3METHODS = ta.CDLRISEFALL3METHODS(o,h,l,c)
    c_SEPARATINGLINES = ta.CDLSEPARATINGLINES(o,h,l,c)
    c_SHOOTINGSTAR = ta.CDLSHOOTINGSTAR(o,h,l,c)
    c_SHORTLINE = ta.CDLSHORTLINE(o,h,l,c)
    c_SPINNINGTOP = ta.CDLSPINNINGTOP(o,h,l,c)
    c_STALLEDPATTERN = ta.CDLSTALLEDPATTERN(o,h,l,c)
    c_STICKSANDWICH = ta.CDLSTICKSANDWICH(o,h,l,c)
    c_TAKURI = ta.CDLTAKURI(o,h,l,c)
    c_TASUKIGAP = ta.CDLTASUKIGAP(o,h,l,c)
    c_THRUSTING = ta.CDLTHRUSTING(o,h,l,c)
    c_TRISTAR = ta.CDLTRISTAR(o,h,l,c)
    c_UNIQUE3RIVER = ta.CDLUNIQUE3RIVER(o,h,l,c)
    c_UPSIDEGAP2CROWS = ta.CDLUPSIDEGAP2CROWS(o,h,l,c)
    c_XSIDEGAP3METHODS = ta.CDLXSIDEGAP3METHODS(o,h,l,c)

    df_2CROWS.loc[len(df_2CROWS)] = [KLSEData[x],c_2CROWS[-1]]
    df_3BLACKCROWS.loc[len(df_3BLACKCROWS)] = [KLSEData[x],c_2CROWS[-1]]
    df_3INSIDE.loc[len(df_3INSIDE)] = [KLSEData[x],c_3BLACKCROWS[-1]]
    df_3LINESTRIKE.loc[len(df_3LINESTRIKE)] = [KLSEData[x],c_3INSIDE[-1]]
    df_3OUTSIDE.loc[len(df_3OUTSIDE)] = [KLSEData[x],c_3LINESTRIKE[-1]]
    df_3STARSINSOUTH.loc[len(df_3STARSINSOUTH)] = [KLSEData[x],c_3OUTSIDE[-1]]
    df_3WHITESOLDIERS.loc[len(df_3WHITESOLDIERS)] = [KLSEData[x],c_3STARSINSOUTH[-1]]
    df_ABANDONEDBABY.loc[len(df_ABANDONEDBABY)] = [KLSEData[x],c_3WHITESOLDIERS[-1]]
    df_ADVANCEBLOCK.loc[len(df_ADVANCEBLOCK)] = [KLSEData[x],c_ABANDONEDBABY[-1]]
    df_BELTHOLD.loc[len(df_BELTHOLD)] = [KLSEData[x],c_ADVANCEBLOCK[-1]]
    df_BREAKAWAY.loc[len(df_BREAKAWAY)] = [KLSEData[x],c_BELTHOLD[-1]]
    df_CLOSINGMARUBOZU.loc[len(df_CLOSINGMARUBOZU)] = [KLSEData[x],c_BREAKAWAY[-1]]
    df_CONCEALBABYSWALL.loc[len(df_CONCEALBABYSWALL)] = [KLSEData[x],c_CLOSINGMARUBOZU[-1]]
    df_COUNTERATTACK.loc[len(df_COUNTERATTACK)] = [KLSEData[x],c_CONCEALBABYSWALL[-1]]
    df_DARKCLOUDCOVER.loc[len(df_DARKCLOUDCOVER)] = [KLSEData[x],c_COUNTERATTACK[-1]]
    df_DOJI.loc[len(df_DOJI)] = [KLSEData[x],c_DARKCLOUDCOVER[-1]]
    df_DOJISTAR.loc[len(df_DOJISTAR)] = [KLSEData[x],c_DOJI[-1]]
    df_DRAGONFLYDOJI.loc[len(df_DRAGONFLYDOJI)] = [KLSEData[x],c_DOJISTAR[-1]]
    df_ENGULFING.loc[len(df_ENGULFING)] = [KLSEData[x],c_DRAGONFLYDOJI[-1]]
    df_EVENINGDOJISTAR.loc[len(df_EVENINGDOJISTAR)] = [KLSEData[x],c_ENGULFING[-1]]
    df_EVENINGSTAR.loc[len(df_EVENINGSTAR)] = [KLSEData[x],c_EVENINGDOJISTAR[-1]]
    df_GAPSIDESIDEWHITE.loc[len(df_GAPSIDESIDEWHITE)] = [KLSEData[x],c_EVENINGSTAR[-1]]
    df_GRAVESTONEDOJI.loc[len(df_GRAVESTONEDOJI)] = [KLSEData[x],c_GAPSIDESIDEWHITE[-1]]
    df_HAMMER.loc[len(df_HAMMER)] = [KLSEData[x],c_GRAVESTONEDOJI[-1]]
    df_HANGINGMAN.loc[len(df_HANGINGMAN)] = [KLSEData[x],c_HAMMER[-1]]
    df_HARAMI.loc[len(df_HARAMI)] = [KLSEData[x],c_HANGINGMAN[-1]]
    df_HARAMICROSS.loc[len(df_HARAMICROSS)] = [KLSEData[x],c_HARAMI[-1]]
    df_HIGHWAVE.loc[len(df_HIGHWAVE)] = [KLSEData[x],c_HARAMICROSS[-1]]
    df_HIKKAKE.loc[len(df_HIKKAKE)] = [KLSEData[x],c_HIGHWAVE[-1]]
    df_HIKKAKEMOD.loc[len(df_HIKKAKEMOD)] = [KLSEData[x],c_HIKKAKE[-1]]
    df_HOMINGPIGEON.loc[len(df_HOMINGPIGEON)] = [KLSEData[x],c_HIKKAKEMOD[-1]]
    df_IDENTICAL3CROWS.loc[len(df_IDENTICAL3CROWS)] = [KLSEData[x],c_HOMINGPIGEON[-1]]
    df_INNECK.loc[len(df_INNECK)] = [KLSEData[x],c_IDENTICAL3CROWS[-1]]
    df_INVERTEDHAMMER.loc[len(df_INVERTEDHAMMER)] = [KLSEData[x],c_INNECK[-1]]
    df_KICKING.loc[len(df_KICKING)] = [KLSEData[x],c_INVERTEDHAMMER[-1]]
    df_KICKINGBYLENGTH.loc[len(df_KICKINGBYLENGTH)] = [KLSEData[x],c_KICKING[-1]]
    df_LADDERBOTTOM.loc[len(df_LADDERBOTTOM)] = [KLSEData[x],c_KICKINGBYLENGTH[-1]]
    df_LONGLEGGEDDOJI.loc[len(df_LONGLEGGEDDOJI)] = [KLSEData[x],c_LADDERBOTTOM[-1]]
    df_LONGLINE.loc[len(df_LONGLINE)] = [KLSEData[x],c_LONGLEGGEDDOJI[-1]]
    df_MARUBOZU.loc[len(df_MARUBOZU)] = [KLSEData[x],c_LONGLINE[-1]]
    df_MATCHINGLOW.loc[len(df_MATCHINGLOW)] = [KLSEData[x],c_MARUBOZU[-1]]
    df_MATHOLD.loc[len(df_MATHOLD)] = [KLSEData[x],c_MATCHINGLOW[-1]]
    df_MORNINGDOJISTAR.loc[len(df_MORNINGDOJISTAR)] = [KLSEData[x],c_MATHOLD[-1]]
    df_MORNINGSTAR.loc[len(df_MORNINGSTAR)] = [KLSEData[x],c_MORNINGDOJISTAR[-1]]
    df_ONNECK.loc[len(df_ONNECK)] = [KLSEData[x],c_MORNINGSTAR[-1]]
    df_PIERCING.loc[len(df_PIERCING)] = [KLSEData[x],c_ONNECK[-1]]
    df_RICKSHAWMAN.loc[len(df_RICKSHAWMAN)] = [KLSEData[x],c_PIERCING[-1]]
    df_RISEFALL3METHODS.loc[len(df_RISEFALL3METHODS)] = [KLSEData[x],c_RICKSHAWMAN[-1]]
    df_SEPARATINGLINES.loc[len(df_SEPARATINGLINES)] = [KLSEData[x],c_RISEFALL3METHODS[-1]]
    df_SHOOTINGSTAR.loc[len(df_SHOOTINGSTAR)] = [KLSEData[x],c_SEPARATINGLINES[-1]]
    df_SHORTLINE.loc[len(df_SHORTLINE)] = [KLSEData[x],c_SHOOTINGSTAR[-1]]
    df_SPINNINGTOP.loc[len(df_SPINNINGTOP)] = [KLSEData[x],c_SHORTLINE[-1]]
    df_STALLEDPATTERN.loc[len(df_STALLEDPATTERN)] = [KLSEData[x],c_SPINNINGTOP[-1]]
    df_STICKSANDWICH.loc[len(df_STICKSANDWICH)] = [KLSEData[x],c_STALLEDPATTERN[-1]]
    df_TAKURI.loc[len(df_TAKURI)] = [KLSEData[x],c_STICKSANDWICH[-1]]
    df_TASUKIGAP.loc[len(df_TASUKIGAP)] = [KLSEData[x],c_TAKURI[-1]]
    df_THRUSTING.loc[len(df_THRUSTING)] = [KLSEData[x],c_TASUKIGAP[-1]]
    df_TRISTAR.loc[len(df_TRISTAR)] = [KLSEData[x],c_THRUSTING[-1]]
    df_UNIQUE3RIVER.loc[len(df_UNIQUE3RIVER)] = [KLSEData[x],c_TRISTAR[-1]]
    df_UPSIDEGAP2CROWS.loc[len(df_UPSIDEGAP2CROWS)] = [KLSEData[x],c_UNIQUE3RIVER[-1]]
    df_XSIDEGAP3METHODS.loc[len(df_XSIDEGAP3METHODS)] = [KLSEData[x],c_UPSIDEGAP2CROWS[-1]]

#df_new = pd.concat([df_mo_active,df_mo_not_active,df_MACD_golden_above0,df_MACD_golden_below0,df_MACD_no_cross,df_no_mo_no_MACD],axis = 1)
#df_new = pd.merge(df_mo_active,df_mo_not_active,df_MACD_golden_above0,df_MACD_golden_below0,df_MACD_no_cross,df_no_mo_no_MACD,on='Stock')
df_1 = pd.merge(df_2CROWS,df_3BLACKCROWS,how='outer',on='Stock')
df_1 = pd.merge(df_1,df_3INSIDE,how='outer',on='Stock')
df_1 = pd.merge(df_1,df_3LINESTRIKE,how='outer',on='Stock')
df_1 = pd.merge(df_1,df_3OUTSIDE,how='outer',on='Stock')
df_1 = pd.merge(df_1,df_3STARSINSOUTH,how='outer',on='Stock')
df_1 = pd.merge(df_1,df_3WHITESOLDIERS,how='outer',on='Stock')
df_1 = pd.merge(df_1,df_ABANDONEDBABY,how='outer',on='Stock')
df_1 = pd.merge(df_1,df_ADVANCEBLOCK,how='outer',on='Stock')
df_1 = pd.merge(df_1,df_BELTHOLD,how='outer',on='Stock')
df_1 = pd.merge(df_1,df_BREAKAWAY,how='outer',on='Stock')
df_1 = pd.merge(df_1,df_CLOSINGMARUBOZU,how='outer',on='Stock')
df_1 = pd.merge(df_1,df_CONCEALBABYSWALL,how='outer',on='Stock')
df_1 = pd.merge(df_1,df_COUNTERATTACK,how='outer',on='Stock')
df_1 = pd.merge(df_1,df_DARKCLOUDCOVER,how='outer',on='Stock')
df_1 = pd.merge(df_1,df_DOJI,how='outer',on='Stock')
df_1 = pd.merge(df_1,df_DOJISTAR,how='outer',on='Stock')
df_1 = pd.merge(df_1,df_DRAGONFLYDOJI,how='outer',on='Stock')
df_1 = pd.merge(df_1,df_ENGULFING,how='outer',on='Stock')
df_1 = pd.merge(df_1,df_EVENINGDOJISTAR,how='outer',on='Stock')
df_1 = pd.merge(df_1,df_EVENINGSTAR,how='outer',on='Stock')
df_1 = pd.merge(df_1,df_GAPSIDESIDEWHITE,how='outer',on='Stock')
df_1 = pd.merge(df_1,df_GRAVESTONEDOJI,how='outer',on='Stock')
df_1 = pd.merge(df_1,df_HAMMER,how='outer',on='Stock')
df_1 = pd.merge(df_1,df_HANGINGMAN,how='outer',on='Stock')
df_1 = pd.merge(df_1,df_HARAMI,how='outer',on='Stock')
df_1 = pd.merge(df_1,df_HARAMICROSS,how='outer',on='Stock')
df_1 = pd.merge(df_1,df_HIGHWAVE,how='outer',on='Stock')
df_1 = pd.merge(df_1,df_HIKKAKE,how='outer',on='Stock')
df_1 = pd.merge(df_1,df_HIKKAKEMOD,how='outer',on='Stock')
df_1 = pd.merge(df_1,df_HOMINGPIGEON,how='outer',on='Stock')
df_1 = pd.merge(df_1,df_IDENTICAL3CROWS,how='outer',on='Stock')
df_1 = pd.merge(df_1,df_INNECK,how='outer',on='Stock')
df_1 = pd.merge(df_1,df_INVERTEDHAMMER,how='outer',on='Stock')
df_1 = pd.merge(df_1,df_KICKING,how='outer',on='Stock')
df_1 = pd.merge(df_1,df_KICKINGBYLENGTH,how='outer',on='Stock')
df_1 = pd.merge(df_1,df_LADDERBOTTOM,how='outer',on='Stock')
df_1 = pd.merge(df_1,df_LONGLEGGEDDOJI,how='outer',on='Stock')
df_1 = pd.merge(df_1,df_LONGLINE,how='outer',on='Stock')
df_1 = pd.merge(df_1,df_MARUBOZU,how='outer',on='Stock')
df_1 = pd.merge(df_1,df_MATCHINGLOW,how='outer',on='Stock')
df_1 = pd.merge(df_1,df_MATHOLD,how='outer',on='Stock')
df_1 = pd.merge(df_1,df_MORNINGDOJISTAR,how='outer',on='Stock')
df_1 = pd.merge(df_1,df_MORNINGSTAR,how='outer',on='Stock')
df_1 = pd.merge(df_1,df_ONNECK,how='outer',on='Stock')
df_1 = pd.merge(df_1,df_PIERCING,how='outer',on='Stock')
df_1 = pd.merge(df_1,df_RICKSHAWMAN,how='outer',on='Stock')
df_1 = pd.merge(df_1,df_RISEFALL3METHODS,how='outer',on='Stock')
df_1 = pd.merge(df_1,df_SEPARATINGLINES,how='outer',on='Stock')
df_1 = pd.merge(df_1,df_SHOOTINGSTAR,how='outer',on='Stock')
df_1 = pd.merge(df_1,df_SHORTLINE,how='outer',on='Stock')
df_1 = pd.merge(df_1,df_SPINNINGTOP,how='outer',on='Stock')
df_1 = pd.merge(df_1,df_STALLEDPATTERN,how='outer',on='Stock')
df_1 = pd.merge(df_1,df_STICKSANDWICH,how='outer',on='Stock')
df_1 = pd.merge(df_1,df_TAKURI,how='outer',on='Stock')
df_1 = pd.merge(df_1,df_TASUKIGAP,how='outer',on='Stock')
df_1 = pd.merge(df_1,df_THRUSTING,how='outer',on='Stock')
df_1 = pd.merge(df_1,df_TRISTAR,how='outer',on='Stock')
df_1 = pd.merge(df_1,df_UNIQUE3RIVER,how='outer',on='Stock')
df_1 = pd.merge(df_1,df_UPSIDEGAP2CROWS,how='outer',on='Stock')
df_1 = pd.merge(df_1,df_XSIDEGAP3METHODS,how='outer',on='Stock')

KESM.xlsx MFLOUR.xlsx PBBANK.xlsx kesm mflour pbbank

bkcollection commented 7 years ago

@mrjbq7 @femtotrader Do you guys able to duplicate my results or you able to get a correct candlestick pattern scan?

pcawthron commented 7 years ago

@bkcollection Have you looked at the C source?

From ta_CDLHAMMER.c

/* Proceed with the calculation for the requested range.
    * Must have:
    * - small real body
    * - long lower shadow
    * - no, or very short, upper shadow
    * - body below or near the lows of the previous candle
    * The meaning of "short", "long" and "near the lows" is specified with TA_SetCandleSettings;
    * outInteger is positive (1 to 100): hammer is always bullish;
    * the user should consider that a hammer must appear in a downtrend, while this function does not consider it
    */
   outIdx = 0;
   do
   {
        if( TA_REALBODY(i) < TA_CANDLEAVERAGE( BodyShort, BodyPeriodTotal, i ) &&                        // small rb
            TA_LOWERSHADOW(i) > TA_CANDLEAVERAGE( ShadowLong, ShadowLongPeriodTotal, i ) &&              // long lower shadow
            TA_UPPERSHADOW(i) < TA_CANDLEAVERAGE( ShadowVeryShort, ShadowVeryShortPeriodTotal, i ) &&    // very short upper shadow
            min( inClose[i], inOpen[i] ) <= inLow[i-1] + TA_CANDLEAVERAGE( Near, NearPeriodTotal, i-1 )  // rb near the prior candle's lows
          )
            outInteger[outIdx++] = 100;
        else
            outInteger[outIdx++] = 0;

So you have to determine that there is a downtrend yourself before applying this indicator. Similarly, you must check for an uptrend before using the other indicator.

From ta_CDLSHOOTINGSTAR.c

/* Proceed with the calculation for the requested range.
    * Must have:
    * - small real body
    * - long upper shadow
    * - no, or very short, lower shadow
    * - gap up from prior real body
    * The meaning of "short", "very short" and "long" is specified with TA_SetCandleSettings;
    * outInteger is negative (-1 to -100): shooting star is always bearish;
    * the user should consider that a shooting star must appear in an uptrend, while this function does not consider it
    */
   outIdx = 0;
   do
   {
        if( TA_REALBODY(i) < TA_CANDLEAVERAGE( BodyShort, BodyPeriodTotal, i ) &&                        // small rb
            TA_UPPERSHADOW(i) > TA_CANDLEAVERAGE( ShadowLong, ShadowLongPeriodTotal, i ) &&              // long upper shadow
            TA_LOWERSHADOW(i) < TA_CANDLEAVERAGE( ShadowVeryShort, ShadowVeryShortPeriodTotal, i ) &&    // very short lower shadow
            TA_REALBODYGAPUP(i, i-1) )                                                                      // gap up
            outInteger[outIdx++] = -100;
        else
            outInteger[outIdx++] = 0;

Also your definitions of the candles may not be the same as those use by the developers of TA-Lib so you need to check the default settings they have used:

From: ta_global.c

TA_RetCode TA_RestoreCandleDefaultSettings( TA_CandleSettingType settingType )
{
    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 }
    };

Would you be able to retest with the trend checks in place?

bkcollection commented 7 years ago

@pcawthron Thanks for your reply.

  1. need to identify the uptrend or downtrend
  2. apply talib candlesticks pattern recognition

the first one, I can add some python code prior using the pattern recognition CDLHAMMER for instance. However, the second one will not be solved as it does not detect the candlesticks correctly. Refer to my previous example for 3 stocks above, the candlesticks pattern is not detect correctly regardless whether I ensure it is an uptrend/downtrend in my code. Do you use the candlesticks for Talib and it is detect the pattern correctly before? I would like to know what I am doing wrongly.

bkcollection commented 7 years ago

@mrjbq7 ,@pcawthron,@femtotrader Any update of this issues which occurred 4 months back?

mrjbq7 commented 7 years ago

I haven't had a chance to look at this -- I don't maintain or develop the underlying ta-lib C library, so if its a bug with their pattern recognition thats not something I am able to patch.

It did occur to me that their pattern recognition is parameterized with these candle settings and it might be a definitional problem where you expect one thing and they are calculating with other assumptions.

bkcollection commented 7 years ago

@mrjbq7 What can we do? Is there anyone who is maintain the ta-lib library that we can feedback to? hope that there is someone who is still working on it.

mrjbq7 commented 7 years ago

It is possible the code has a bug in it, but also possible it's definition is a little different than yours. Have you looked at the C code to see where it differs from your understanding of the pattern?

The original author hasn't done a release in awhile, but there was some activity a few years ago on SourceForge. Not sure the best way to contact them, but perhaps if there is a bug, they can do a fix and release.

mrjbq7 commented 7 years ago

Maybe report the bug here:

https://sourceforge.net/p/ta-lib/bugs/?source=navbar

bkcollection commented 7 years ago

@mrjbq7 Feel like a waste that such a good library has no one maintained anymore. The link you given also not active. I think the people in Github are more active than at sourceforge. I find some are discussion of the accuracy of Ta-Lib pattern recognition at Quantopian which is python environment as well. Unable to find any which using other languages. As point out by @pcawthron previously, I do find the description in C language correct but the result is not By the way, I do not know much about C language

A best comparison to verify is using finviz for US stocks which it has some candlesticks pattern and compare using python Ta-Lib. example: One of the stocs 'ABAC' is screen having a Hammer pattern by finviz https://finviz.com/screener.ashx?v=171&f=ta_candlestick_h&ft=3

But when using Ta-Lib, no pattern found.

`>>> stock=web.DataReader('ABAC', 'yahoo', '2017-1-1','2017-2-2')

high = stock.High>>> low = stock.Low close = stock['Adj Close'] open = stock.Open c = np.array(close) l = np.array(low) o = np.array(open) h=np.array(high) ta.CDLHAMMER(o,h,l,c) array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], dtype=int32)`

mrjbq7 commented 7 years ago

The link I gave has bug tickets reported and commented on it looks like in the last year? I don't see any commits on sourceforge SVN though.

redbullpeter commented 7 years ago

Yeah work on the code has pretty much ground to a halt. Maybe fork it on to github?

mrjbq7 commented 7 years ago

I wonder if there are any copyright / license issues in doing that. Since the original author was trying to make a company that provided support and changes. Need to look into that. Not a bad idea.

redbullpeter commented 7 years ago

It's under BSD License. So no issues there. The paid part is for Excel plugins.

bkcollection commented 7 years ago

@mrjbq7 @redbullpeter

Seems like if there are people who able and willing contribute, Ta-Lib in python can be alive and continue to improve. It is a good news.

harikongu commented 6 years ago

@bkcollection I am new to ta-lib. Can we trust ta-lib's Pattern Recognition?