Search code examples
python-3.xpandasplotlyfinancecandlestick-chart

Identify and extract OHLC pattern on candlestick chart using plotly or pandas?


I'm using the Ameritrade API and pandas/plotly to chart a simple stock price on the minute scale, I'd like to use some of the properties of the produced chart to identify and extract a specific candlestick pattern.

Here I build my dataframe and plot it as a candlestick:

frame = pd.DataFrame({'open': pd.json_normalize(df, 'candles').open,
                     'high': pd.json_normalize(df, 'candles').high,
                     'low': pd.json_normalize(df, 'candles').low,
                     'close': pd.json_normalize(df, 'candles').close,
                     'datetime': pd.DatetimeIndex(pd.to_datetime(pd.json_normalize(df, 'candles').datetime, unit='ms')).tz_localize('UTC').tz_convert('US/Eastern')})


fig = go.Figure(data=[go.Candlestick(x=frame['datetime'],
                                    open=frame['open'],
                                    high=frame['high'],
                                    low=frame['low'],
                                    close=frame['close'])])
fig.update_layout(xaxis_rangeslider_visible=False)
fig.show()

The plot:

The pattern I'm searching for is simply the very first set in each day's trading of four consecutive red candles.

A red candle can be defined as:

close < open & close < prev.close

So in this case, I don't have access to prev.close for the very first minute of trading because I don't have pre-market/extended hours data.

I'm wondering if it's even possible to access the plotly figure data, because if so, I could just extract the first set of four consecutive red candles, and their data - but if not, I would just define my pattern and extract it using pandas but haven't gotten that far yet.

Would this be easier to do using plotly or pandas, and what would a simple implementation look like?


Solution

  • Not sure about Candlestick, but in pandas, you could try something like this. Note: I assume the data have 1 row for each business day already and is sorted. The first thing is to create a column named red with True where the condition for a red candle as described in you question is True:

    df['red'] = df['close'].lt(df['open'])&df['close'].lt(df['close'].shift())
    

    Then you want to see if it happens 4 days in a row and assuming the data is sorted ascending (usually), the idea is to reverse the dataframe with [::-1], use rolling with a window of 4, sum the column red created just above and check where it is equal to 4.

    df['next_4days_red'] = df[::-1].rolling(4)['red'].sum().eq(4)
    

    then if you want the days that are at the beginning of 4 consecutive red trading days you do loc:

    df.loc[df['next_4days_red'], 'datetime'].tolist()
    

    Here with a little example with dummy varaibles:

    df = pd.DataFrame({'close': [10,12,11,10,9,8,7,10,9,10], 
                       'datetime':pd.bdate_range('2020-04-01', periods=10 )})\
           .assign(open=lambda x: x['close']+0.5)
    df['red'] = df['close'].lt(df['open'])&df['close'].lt(df['close'].shift())
    df['next_4days_red'] = df[::-1].rolling(4)['red'].sum().eq(4)
    
    print (df.loc[df['next_4days_red'], 'datetime'].tolist())
    [Timestamp('2020-04-03 00:00:00'), Timestamp('2020-04-06 00:00:00')]
    

    Note: it catches two successive dates because it is a 5 days consecutive decrease, not sure if in this case you wanted the two dates