Search code examples
pythonpandasfinance

How to scan multiple variables simultaneously in my python candlestick scanner?


This is the code for my candlestick scanner. My aim is to scan multiple variables simultaneously however when my code runs it only results in a single column of false. If anyone knows how to scan multiple tickers at once it will help tremendously.

import datetime as dt 
import pandas_datareader as web
import pandas as pd

start = dt.datetime(2020,12,31)
end = dt.datetime.now()
Stock = ('ANZ.AX','APT.AX','FMG.AX')

df = web.DataReader(Stock, 'yahoo', start, end)

# Change data to omit volume and adjusted close (can change later to display volume)
data = df[['Open', 'High', 'Low', 'Close']]

for i in range(2, df.shape[0]):
    current = df.iloc[i, :]
    prev = df.iloc[i - 1, :]
    prev_2 = df.iloc[i - 2, :]

    realbody = abs(current['Open'] - current['Close'])
    candle_range = current['High'] - current['Low']

    idx = df.index[i]

    # Bullish engulfing
    df.loc[idx, 'Bullish Engulfing'] = (prev['Open'] > prev['Close']) & (current['Close'] > current['Open']) \
    & (current['High'] > prev['High']) & (current['Low'] < prev['Low'])

df.fillna(False, inplace=True)

pd.set_option('display.max_columns', None)
pd.set_option('display.max_rows', None)
print(df['Bullish Engulfing'])

Resulted code:

Date
2020-12-30    False
2021-01-03    False
2021-01-05    False
Name: Bullish Engulfing, dtype: bool

Solution

  • the issue is you have a multindex on the columns

    import datetime as dt 
    import pandas_datareader as web
    import pandas as pd
    
    start = dt.datetime(2020,12,31)
    end = dt.datetime.now()
    Stock = ('ANZ.AX','APT.AX','FMG.AX')
    
    df = web.DataReader(Stock, 'yahoo', start, end)
    
    df.columns
    

    gives

    MultiIndex([('Adj Close', 'ANZ.AX'),
                ('Adj Close', 'APT.AX'),
                ('Adj Close', 'FMG.AX'),
                (    'Close', 'ANZ.AX'),
                (    'Close', 'APT.AX'),
                (    'Close', 'FMG.AX'),
                (     'High', 'ANZ.AX'),
                (     'High', 'APT.AX'),
                (     'High', 'FMG.AX'),
                (      'Low', 'ANZ.AX'),
                (      'Low', 'APT.AX'),
                (      'Low', 'FMG.AX'),
                (     'Open', 'ANZ.AX'),
                (     'Open', 'APT.AX'),
                (     'Open', 'FMG.AX'),
                (   'Volume', 'ANZ.AX'),
                (   'Volume', 'APT.AX'),
                (   'Volume', 'FMG.AX')],
               names=['Attributes', 'Symbols'])
    

    where in your code you go current = df.iloc[i, :] it is not giving you what you think as you still have a multi index

    current = df.iloc[1, :]
    

    for example yeilds

    Attributes  Symbols
    Adj Close   ANZ.AX     2.304000e+01
                APT.AX     1.190000e+02
                FMG.AX     2.480000e+01
    Close       ANZ.AX     2.304000e+01
                APT.AX     1.190000e+02
                FMG.AX     2.480000e+01
    High        ANZ.AX     2.314000e+01
                APT.AX     1.223000e+02
                FMG.AX     2.480000e+01
    Low         ANZ.AX     2.276000e+01
                APT.AX     1.190000e+02
                FMG.AX     2.370000e+01
    Open        ANZ.AX     2.276000e+01
                APT.AX     1.196800e+02
                FMG.AX     2.371000e+01
    Volume      ANZ.AX     3.207879e+06
                APT.AX     9.625380e+05
                FMG.AX     6.402739e+06
    Name: 2021-01-03 00:00:00, dtype: float64
    

    so when you write back df.loc[idx, 'Bullish Engulfing'] this is not stock specific.

    you would be better off with a groupby and doing it all stock by stock.

    Pandas Multiindex Groupby on Columns will show you how to do that.