# Detect candlestick patterns using TA-Lib and Python

As an Amazon Associate I earn from qualifying purchases.

Candlestick patterns can be a great way of deciding if and when we should open or close a trade. For example, if we get a ‘hammer’ candlestick, this is usually a bullish sign. Paired with a moving average, this can be a powerful strategy. Let’s have a look at how we can detect candlestick patterns using TA-Lib and Python with the algorithmic trading bot.

For this tutorial, I will be using the hammer candlestick as an example. A full list of detectable candlestick patterns can be found here.

Contents

## Adding candlestick patterns as constants

In TA-lib, candlestick patterns are functions that usually take the following form: CANDLESTICK(open, high, low, close). To reference these candlestick functions in our strategy (`strategy.json`), I found it best to add all the candlestick functions to a dictionary in `constants.py` using lambda expressions

Add the following code to `constants.py`:

``````cs_patterns = {
'hammer' : lambda openP, high, low, close: ta.CDLHAMMER(openP, high, low, close),
'closingMarubozu' : lambda openP, high, low, close:  ta.CDLCLOSINGMARUBOZU(openP, high, low, close),
'doji' : lambda openP, high, low, close: ta.CDLDOJI(openP, high, low, close),
'engulfing' : lambda openP, high, low, close:  ta.CDLENGULFING(openP, high, low, close),
'hangingMan' : lambda openP, high, low, close: ta.CDLHANGINGMAN(openP, high, low, close),
'hammer' : lambda openP, high, low, close: ta.CDLHAMMER(openP, high, low, close),
'invertedHammer' : lambda openP, high, low, close: ta.CDLINVERTEDHAMMER(openP, high, low, close),
'marubozu' : lambda openP, high, low, close: ta.CDLMARUBOZU(openP, high, low, close),
'beltHold': lambda openP, high, low, close: ta.CDLBELTHOLD(openP, high, low, close),
'breakaway' : lambda openP, high, low, close: ta.CDLBREAKAWAY(openP, high, low, close),
'inNeck' : lambda openP, high, low, close: ta.CDLINNECK(openP, high, low, close),
'kicking': lambda openP, high, low, close: ta.CDLKICKING(openP, high, low, close),
'kickingByLength' : lambda openP, high, low, close: ta.CDLKICKINGBYLENGTH(openP, high, low, close),
'longLeggedDoji' : lambda openP, high, low, close: ta.CDLLONGLEGGEDDOJI(openP, high, low, close),
'longLineCdl' : lambda openP, high, low, close: ta.CDLLONGLINE(openP, high, low, close),
'shortLineCdl' : lambda openP, high, low, close: ta.CDLSHORTLINE(openP, high, low, close),
'rickShawMan' : lambda openP, high, low, close: ta.CDLRICKSHAWMAN(openP, high, low, close),
'spinningTop' : lambda openP, high, low, close: ta.CDLSPINNINGTOP(openP, high, low, close),
'stalled' : lambda openP, high, low, close: ta.CDLSTALLEDPATTERN(openP, high, low, close),
'stickSandwhich' : lambda openP, high, low, close: ta.CDLSTICKSANDWICH(openP, high, low, close),
'takuri' : lambda openP, high, low, close: ta.CDLTAKURI(openP, high, low, close),
'tasukiGap' : lambda openP, high, low, close: ta.CDLTASUKIGAP(openP, high, low, close),
'stalled' : lambda openP, high, low, close: ta.CDLSTALLEDPATTERN(openP, high, low, close),
'thrusting' : lambda openP, high, low, close: ta.CDLTHRUSTING(openP, high, low, close),
}``````

Using this dictionary, you will now be able to reference and candlestick pattern function by it’s key.

## Adding a candlestick pattern to our strategy

In the strategy file, you will want to specify the candlestick pattern key. Add a new key under the `movingAverages` key and name it `candlestickPattern`. Set the value of this key to `hammer`:

``````{
"accountNumber" : 40461345,
"account_currency" : "USD",
"strategy_name": "myStrategy",
"pairs": [
"EURUSD",
"GBPUSD"
],
"risk" : 2,
"maxLosses" : 3,
"takeProfit": 700.0,
"stopLoss": 300.0,
"movingAverages": {
"SMA": {
"val": 10,
"aboveBelow": "below"
},
"EMA": {
"val": 50,
"aboveBelow": "above"
}
},
"candlestickPattern" : "hammer",
"maximumDrawdown" : 0.5,
"initialBalance" : 100000
}``````

## Detecting the candlestick pattern during live trading

The last step is to calculate the current candlestick for the current period and detect if it is the candlestick you are interested in trading. To do this, let’s go back to the `check_trades` method in `trader.py`. The `check_trades` method should look similar to the following:

``````def check_trades(time_frame, pair_data, strategy):
moving_averages = strategy['movingAverages']
for pair, data in pair_data.items():
for m in moving_averages:
ma_func = constants.movingAveragesFunctions[m]
val = moving_averages [m]['val']
data[m] = ma_func(data['close'], val)

last_row = data.tail(1)
open_positions = positions_get()
current_dt = datetime.now().astimezone(pytz.timezone('Europe/Athens'))
for index, position in open_positions.iterrows():
# Check to see if the trade has exceeded the time limit
deal_id = position['ticket']
if(current_dt - trade_open_dt >= timedelta(hours = 2)):
close_position(deal_id)

for index, last in last_row.iterrows():
#Exit strategy
if(last['close'] < last['EMA'] and last['close'] > last['SMA']):
close_positon_by_symbol(pair)

print("Daily losses have been exceeded. Not executing any more trades today")
continue

#Entry strategy
if(last['close'] > last['EMA'] and last['close'] < last['SMA']):
lot_size = calc_position_size(pair, strategy)
open_position(pair, "BUY", lot_size, float (strategy['takeProfit']), float(strategy['stopLoss']))``````

In the last for loop, you are iterating over the newest tick data for the current period. Just before this loop starts, let’s calculate what kind of candlestick pattern you currently have. Find the corresponding candlestick pattern function by getting the candlestick pattern key defined in your strategy:

``        candlestick_func = constants.cs_patterns[strategy['candlestickPattern']]``

Now, you should call `candlestick_func` passing in the `open`, `high`, `low`, `close` data from the `last_row` data frame and assign the output of this function to `last_row['is_cs_pattern']`:

``        last_row['is_cs_pattern'] = candlestick_func(last_row['open'], last_row['high'], last_row['low'], last_row['close'])``

Running the candle stick function will simply give you a boolean TRUE or FALSE if the specified candlestick pattern has been detected or not.

Finally, go to the last loop in the `check_trades` method and find this code block:

``````            #Entry strategy
if(last['close'] > last['EMA'] and last['close'] < last['SMA']):
lot_size = calc_position_size(pair, strategy)
open_position(pair, "BUY", lot_size, float (strategy['takeProfit']), float(strategy['stopLoss']))``````

You will want to modify the if condition to add if the candlestick pattern has been found or not. This can be done as follows:

``            if(last['close'] > last['EMA'] and last['close'] < last['SMA'] and last['is_cs_pattern']):``