Skip to content

Commit

Permalink
v1.19 - Search for Stocks reversed at MA
Browse files Browse the repository at this point in the history
  • Loading branch information
pranjal-joshi committed Jun 6, 2021
1 parent 8974181 commit 9484ddb
Show file tree
Hide file tree
Showing 7 changed files with 50 additions and 18 deletions.
4 changes: 3 additions & 1 deletion src/classes/Changelog.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

from classes.ColorText import colorText

VERSION = "1.18"
VERSION = "1.19"

changelog = colorText.BOLD + '[ChangeLog]\n' + colorText.END + colorText.BLUE + '''
[1.00 - Beta]
Expand Down Expand Up @@ -97,5 +97,7 @@
1. Cache and Performance fixes.
2. Breakout Calculation Enhanced.
[1.19]
1. New Feature: Search for Bullish Reversal at MA. Option > 6 > 4
--- END ---
''' + colorText.END
7 changes: 6 additions & 1 deletion src/classes/ParallelProcessing.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ def run(self):
except Exception as e:
sys.exit(0)

def screenStocks(self, executeOption, reversalOption, daysForLowestVolume, minRSI, maxRSI, respBullBear, insideBarToLookback, totalSymbols,
def screenStocks(self, executeOption, reversalOption, maLength, daysForLowestVolume, minRSI, maxRSI, respBullBear, insideBarToLookback, totalSymbols,
configManager, fetcher, screener, candlePatterns, stock, printCounter=False):
screenResults = pd.DataFrame(columns=[
'Stock', 'Consolidating', 'Breaking-Out', 'MA-Signal', 'Volume', 'LTP', 'RSI', 'Trend', 'Pattern'])
Expand Down Expand Up @@ -129,6 +129,8 @@ def screenStocks(self, executeOption, reversalOption, daysForLowestVolume, minRS
isInsideBar = screener.validateInsideBar(
processedData, screeningDictionary, saveDictionary, bullBear=respBullBear, daysToLookback=insideBarToLookback)
isMomentum = screener.validateMomentum(processedData, screeningDictionary, saveDictionary)
if maLength is not None and executeOption == 6:
isMaSupport = screener.findReversalMA(fullData, screeningDictionary, saveDictionary, maLength)

with self.screenResultsCounter.get_lock():
if executeOption == 0 or executeOption == 'W':
Expand Down Expand Up @@ -158,6 +160,9 @@ def screenStocks(self, executeOption, reversalOption, daysForLowestVolume, minRS
elif reversalOption == 3 and isMomentum:
self.screenResultsCounter.value += 1
return screeningDictionary, saveDictionary
elif reversalOption == 4 and isMaSupport:
self.screenResultsCounter.value += 1
return screeningDictionary, saveDictionary
if executeOption == 7 and isLtpValid and isInsideBar:
self.screenResultsCounter.value += 1
return screeningDictionary, saveDictionary
Expand Down
17 changes: 17 additions & 0 deletions src/classes/Screener.py
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,23 @@ def validateMomentum(self, data, screenDict, saveDict):
traceback.print_exc()
return False

# Find stock reversing at given MA
def findReversalMA(self, data, screenDict, saveDict, maLength, percentage=0.015):
if maLength is None:
maLength = 20
data = data[::-1]
if self.configManager.useEMA:
maRev = talib.EMA(data['Close'],timeperiod=maLength)
else:
maRev = talib.MA(data['Close'],timeperiod=maLength)
data.insert(10,'maRev',maRev)
data = data[::-1].head(3)
if data.equals(data[(data.Close >= (data.maRev - (data.maRev*percentage))) & (data.Close <= (data.maRev + (data.maRev*percentage)))]) and data.head(1)['Close'][0] >= data.head(1)['maRev'][0]:
screenDict['MA-Signal'] = colorText.BOLD + colorText.GREEN + f'Reversal-{maLength}MA' + colorText.END
saveDict['MA-Signal'] = f'Reversal-{maLength}MA'
return True
return False

'''
# Find out trend for days to lookback
def validateVCP(data, screenDict, saveDict, daysToLookback=ConfigManager.daysToLookback, stockName=None):
Expand Down
13 changes: 10 additions & 3 deletions src/classes/Utility.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,13 +167,20 @@ def promptReversalScreening():
1 > Screen for Buy Signal (Bullish Reversal)
2 > Screen for Sell Signal (Bearish Reversal)
3 > Screen for Momentum Gainers (Rising Bullish Momentum)
4 > Screen for Reversal at Moving Average (Bullish Reversal)
0 > Cancel
[+] Select option: """ + colorText.END))
if resp >= 0 and resp <= 3:
return resp
if resp >= 0 and resp <= 4:
if resp == 4:
try:
maLength = int(input(colorText.BOLD + colorText.WARN + '\n[+] Enter MA Length (E.g. 20/50): ' + colorText.END))
return resp, maLength
except ValueError:
raise ValueError
return resp, None
raise ValueError
except ValueError:
return None
return None, None

# Prompt for Reversal screening
def promptChartPatterns():
Expand Down
18 changes: 9 additions & 9 deletions src/release.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
# Make sure to download the latest release! ![GitHub release (latest by date)](https://img.shields.io/github/v/release/pranjal-joshi/Screeni-py)

## What's New?
1. Now **Create Your Own Watchlist** in Excel and screen for only those stocks! Try `Option > W` :chart_with_upwards_trend:
2. New Improved **Breakout Detection.** :rocket:
3. New **Chart Pattern** **`Bullish Momentum Gainer`** added! Try `Option > 6 > 3` :tada:
4. **Data Saver & High Performance Mode**: Intellegently Stores Stock Data for After-Market hours screening without using extra bandwidth. Also, uses multiple CPU cores available on your computer for supperfast screening! :sparkles: (Thanks to [**swarpatel23**](https://github.com/swarpatel23))
5. Cosmetic Updates - Progressbar for showing screening process! :lipstick:
6. Performance Upgrades! :gear:
1. Search stocks which are **Reversed** by taking Support at Moving Average! Try `Option > 6 > 4`.
2. Now **Create Your Own Watchlist** in Excel and screen for only those stocks! Try `Option > W` :chart_with_upwards_trend:
3. New Improved **Breakout Detection.** :rocket:
4. New **Chart Pattern** **`Bullish Momentum Gainer`** added! Try `Option > 6 > 3` :tada:
5. **Data Saver & High Performance Mode**: Intellegently Stores Stock Data for After-Market hours screening without using extra bandwidth. Also, uses multiple CPU cores available on your computer for supperfast screening! :sparkles: (Thanks to [**swarpatel23**](https://github.com/swarpatel23))
6. Cosmetic Updates - Progressbar for showing screening process! :lipstick:

## Downloads
* For :desktop_computer: **Windows** users, download **[screenipy.exe](https://github.com/pranjal-joshi/Screeni-py/releases/download/1.18/screenipy.exe)**
* For :penguin: **Linux** users, download **[screenipy.bin](https://github.com/pranjal-joshi/Screeni-py/releases/download/1.18/screenipy.bin)**
* For :apple: **MacOS** users, download **[screenipy.run](https://github.com/pranjal-joshi/Screeni-py/releases/download/1.18/screenipy.run)** ([Read Installation Guide](https://github.com/pranjal-joshi/Screeni-py/blob/main/INSTALLATION.md#for-macos))
* For :desktop_computer: **Windows** users, download **[screenipy.exe](https://github.com/pranjal-joshi/Screeni-py/releases/download/1.19/screenipy.exe)**
* For :penguin: **Linux** users, download **[screenipy.bin](https://github.com/pranjal-joshi/Screeni-py/releases/download/1.19/screenipy.bin)**
* For :apple: **MacOS** users, download **[screenipy.run](https://github.com/pranjal-joshi/Screeni-py/releases/download/1.19/screenipy.run)** ([Read Installation Guide](https://github.com/pranjal-joshi/Screeni-py/blob/main/INSTALLATION.md#for-macos))

## How to use?

Expand Down
2 changes: 1 addition & 1 deletion src/screenipy.ini
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ consolidationpercentage = 10
shuffle = y
cachestockdata = y
onlystagetwostocks = y
useema = y
useema = n

7 changes: 4 additions & 3 deletions src/screenipy.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
keyboardInterruptEvent = None
loadedStockData = False
loadCount = 0
maLength = None

configManager = ConfigManager.tools()
fetcher = Fetcher.tools(configManager)
Expand Down Expand Up @@ -94,7 +95,7 @@ def initExecution():


def main(testing=False):
global screenCounter, screenResultsCounter, stockDict, loadedStockData, keyboardInterruptEvent, loadCount
global screenCounter, screenResultsCounter, stockDict, loadedStockData, keyboardInterruptEvent, loadCount, maLength
screenCounter = multiprocessing.Value('i', 1)
screenResultsCounter = multiprocessing.Value('i', 0)
keyboardInterruptEvent = multiprocessing.Manager().Event()
Expand Down Expand Up @@ -141,7 +142,7 @@ def main(testing=False):
input('')
main()
if executeOption == 6:
reversalOption = Utility.tools.promptReversalScreening()
reversalOption, maLength = Utility.tools.promptReversalScreening()
if reversalOption is None or reversalOption == 0:
main()
if executeOption == 7:
Expand Down Expand Up @@ -188,7 +189,7 @@ def main(testing=False):
print(colorText.BOLD + colorText.WARN +
"[+] Starting Stock Screening.. Press Ctrl+C to stop!\n")

items = [(executeOption, reversalOption, daysForLowestVolume, minRSI, maxRSI, respBullBear, insideBarToLookback, len(listStockCodes),
items = [(executeOption, reversalOption, maLength, daysForLowestVolume, minRSI, maxRSI, respBullBear, insideBarToLookback, len(listStockCodes),
configManager, fetcher, screener, candlePatterns, stock)
for stock in listStockCodes]

Expand Down

0 comments on commit 9484ddb

Please sign in to comment.