admin 發表於 2023-4-17 07:44:27

Create a Watchlist of Trending Stocks with Python

it's important to have a system in place to pare down the number of charts that are worth a closer look.
my search for trends is always for rising stocks.
this doesn't generate a list of recommended positions, but a list of tickers worth a closer look via charts, fundamentals, and macro/broader market conditions.
the basic idea is to apply conditional checks and filtering to your entire ticker universe of prices, returning only those tickers that have short-term simple moving averages (SMAs) that are higher than longer-term ones, across a specified range of days.
we also filter out any ticker that has had a gap in either direction greater than 10% (using absolute value) within the date range.
The specific conditions to be coded are:

[*]20-period SMA > 50-period SMA for the last 100 days
[*]50-period SMA > 200-period SMA for the last 100 days
[*]No gaps (up or down) for the last 100 days between a day's opening price and the prior day's close > 10% (abs value)
[*]Each day's trading volume >= 200,000 shares
1) a single csv file of the entire Quandl/Sharadar EOD Equity Prices databy importing it into my Python environment as a pandas data frame.

import pandas as pd


#read in the data set, drop the columns not needed, and make sure 'tradeDate' col
#is datetime data type

df = pd.read_csv('..\\appData\\dailyEquityData.csv')
df = df[['ticker', 'tradeDate', 'open', 'close', 'volume']]
df['tradeDate'] = pd.to_datetime(df['tradeDate'])https://media.licdn.com/dms/image/C4E12AQFO4gWlhWRGjA/article-inline_image-shrink_1000_1488/0/1580080070534?e=1686787200&v=beta&t=vNAnbCg75en29rPFpPfGm5iOU7OR-P6KWZr9CI2AS0M2)to get the latest date of the tradeDate column, and then filter the data to return rows where the trade date equals that value.#get the tickers that have the maxDate in their tradeDate column

latest_tickers = df==maxDate].ticker
df = df.isin(latest_tickers)]Now we set the ticker and tradeDate columns as a multi-level index.
#set the multindex, without dropping the columns

df.set_index(['ticker', 'tradeDate'], inplace=True, drop=False)
df.sort_index(inplace=True)3)to add the moving averages, and get a lagged value of the prior day's close, which we use to filter out price gaps.
#add the moving average columns and the prior close to each row

df['sma20'] = df.groupby(level=0).close.apply(lambda x: x.rolling(20).mean())
df['sma50'] = df.groupby(level=0).close.apply(lambda x: x.rolling(50).mean())
df['sma200'] = df.groupby(level=0).close.apply(lambda x: x.rolling(200).mean())
df['priorClose'] = df.groupby(level=0).close.shift(1)The moving average calculations need their respective number of data points before they can return values.
For this reason, there are a bunch of NaN values in the data frame.
https://media.licdn.com/dms/image/C4E12AQESlVSeJwgqWw/article-inline_image-shrink_1000_1488/0/1580081146285?e=1686787200&v=beta&t=E4rOABa1RKnVDI4DC9VL60ElmEIKunQO2HAnGh92_pw
These rows aren't needed anyway, so we'll remove them. 4)The next step after that is to get the latest 100 data points for each ticker.#drop all na values, and get the latest 100 data points for each ticker

df.dropna(inplace=True)
df = df.groupby(level=0).tail(100) use the tail function on the data frame to show that we're working with the latest data points. https://media.licdn.com/dms/image/C4E12AQGJ4t88mRLKbA/article-inline_image-shrink_1000_1488/0/1580081338100?e=1686787200&v=beta&t=1pB-1annV9rAC-YOJVDgz_olqFw9v03P5O55lG2JgzA
And now the moment of truth, literally... 5)add a boolean column to the data frame for each condition we wish to check. The last one confirms that all of the conditions required are true.#add a boolean column for each filter condition as well as a check that all = True

df['notBigGapOpen'] = abs(((df['open'] / df['priorClose']) - 1) < 0.10)
df['sma20gtsma50'] = df['sma20'] > df['sma50']
df['sma50gtsma200'] = df['sma50'] > df['sma200']
df['adequateVol'] = df['volume'] >= 200000
df['rowPassed'] = (df['notBigGapOpen'] & df['sma20gtsma50'] & df['sma50gtsma200'] &
                  df['adequateVol'])https://media.licdn.com/dms/image/C4E12AQEJDXr4qBUq_g/article-inline_image-shrink_1500_2232/0/1580081524890?e=1686787200&v=beta&t=FRoYdjTG_c-W6XomplKFEJgWOjCrX4pFrAUZLFPziC4
At this point, our data set has the latest 100 data points for each ticker. The conditional checks are in place for each data point. All that is left to do is reduce the data to those tickers that have a rowPassed = True for every one of the 100 rows. We can do this by aggregating on the ticker, and calling the sum function on the rowPassed column. Since numerically, each False value equals 0, and each True value equals 1, each ticker that has a True in all of the rows will have a sum of 100. Those tickers are our watchlist of trending stocks.#for each ticker, see if the rowPassed col is true for each data point. sum the boolean
#values, and then filter for those tickers that have a sum = 100 (the count of the rows
#for each ticker)

df_sums = pd.DataFrame(df.groupby(level=0).rowPassed.sum())
trending_tickers = df_sums==100].indexhttps://media.licdn.com/dms/image/C4E12AQEAZTCkpFRr_g/article-inline_image-shrink_1000_1488/0/1580082030729?e=1686787200&v=beta&t=JgBLaj4eU5FVGAXCNt5hHXIuT8mwcctgsilber9EHIQ
We started with over 6,000 tickers, and reduced it to a mere 34. Admittedly, this is a fairly strict definition of an uptrend. It's likely that there are many nice potential trade setups that have been filtered out; but 34 charts to review on a daily basis is more realistic than 6,000+, and the coded parameters can be adjusted and optimized.
While writing this, I used two data sets I knew to have strong trends, Apple (AAPL) and Google (GOOG).
Both made the cut, and are in the final list. The charts await:
https://media.licdn.com/dms/image/C4E12AQGZ9iayt3u0jg/article-inline_image-shrink_1000_1488/0/1580082673751?e=1686787200&v=beta&t=r63qPIQySPFO8Yy43ux5Fcxqm7QZTAf4LtWzp1JlR2Yhttps://media.licdn.com/dms/image/C4E12AQHrc10u7E8n9Q/article-inline_image-shrink_1000_1488/0/1580082687795?e=1686787200&v=beta&t=8sj-P4Pt7hiZskCOIuxwXlMlU_OsA-Z5z78fJrUh55k




頁: [1]
查看完整版本: Create a Watchlist of Trending Stocks with Python