Skip to content

Commit

Permalink
v1.18 - Performance & Algo Upgrades
Browse files Browse the repository at this point in the history
[Screenipy Test] New Features Added - Test Passed - Merge OK
  • Loading branch information
pranjal-joshi authored May 30, 2021
2 parents 4cfc63f + df4393b commit 8974181
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 39 deletions.
6 changes: 5 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.17"
VERSION = "1.18"

changelog = colorText.BOLD + '[ChangeLog]\n' + colorText.END + colorText.BLUE + '''
[1.00 - Beta]
Expand Down Expand Up @@ -93,5 +93,9 @@
2. Progressbar added.
3. Watchlist creation in Excel file and its screening.
[1.18]
1. Cache and Performance fixes.
2. Breakout Calculation Enhanced.
--- END ---
''' + colorText.END
11 changes: 4 additions & 7 deletions src/classes/Screener.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,9 +176,6 @@ def findBreakout(self, data, screenDict, saveDict, daysToLookback):
data = data.fillna(0)
data = data.replace([np.inf, -np.inf], 0)
recent = data.head(1)
# Consider only for Green Candle
if not self.getCandleType(recent):
return False
data = data[1:]
hs = round(data.describe()['High']['max'],2)
hc = round(data.describe()['Close']['max'],2)
Expand All @@ -188,28 +185,28 @@ def findBreakout(self, data, screenDict, saveDict, daysToLookback):
saveDict['Breaking-Out'] = str(hc)
if rc >= hc:
screenDict['Breaking-Out'] = colorText.BOLD + colorText.GREEN + "BO: " + str(hc) + " R: " + str(hs) + colorText.END
return True
return True and self.getCandleType(recent)
screenDict['Breaking-Out'] = colorText.BOLD + colorText.FAIL + "BO: " + str(hc) + " R: " + str(hs) + colorText.END
return False
noOfHigherShadows = len(data[data.High > hc])
if(daysToLookback/noOfHigherShadows <= 3):
saveDict['Breaking-Out'] = str(hs)
if rc >= hs:
screenDict['Breaking-Out'] = colorText.BOLD + colorText.GREEN + "BO: " + str(hs) + colorText.END
return True
return True and self.getCandleType(recent)
screenDict['Breaking-Out'] = colorText.BOLD + colorText.FAIL + "BO: " + str(hs) + colorText.END
return False
saveDict['Breaking-Out'] = str(hc) + ", " + str(hs)
if rc >= hc:
screenDict['Breaking-Out'] = colorText.BOLD + colorText.GREEN + "BO: " + str(hc) + " R: " + str(hs) + colorText.END
return True
return True and self.getCandleType(recent)
screenDict['Breaking-Out'] = colorText.BOLD + colorText.FAIL + "BO: " + str(hc) + " R: " + str(hs) + colorText.END
return False
else:
saveDict['Breaking-Out'] = str(hc)
if rc >= hc:
screenDict['Breaking-Out'] = colorText.BOLD + colorText.GREEN + "BO: " + str(hc) + colorText.END
return True
return True and self.getCandleType(recent)
screenDict['Breaking-Out'] = colorText.BOLD + colorText.FAIL + "BO: " + str(hc) + colorText.END
return False

Expand Down
84 changes: 59 additions & 25 deletions src/classes/Utility.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
lastScreened = 'last_screened_results.pkl'

# Class for managing misc and utility methods


class tools:

def clearScreen():
Expand All @@ -46,11 +48,16 @@ def clearScreen():
# Print about developers and repository
def showDevInfo():
print('\n'+changelog)
print(colorText.BOLD + colorText.WARN + "\n[+] Developer: Pranjal Joshi." + colorText.END)
print(colorText.BOLD + colorText.WARN + ("[+] Version: %s" % VERSION) + colorText.END)
print(colorText.BOLD + colorText.WARN + "[+] More: https://github.com/pranjal-joshi/Screeni-py" + colorText.END)
print(colorText.BOLD + colorText.WARN + "[+] Post Feedback/Issues here: https://github.com/pranjal-joshi/Screeni-py/issues" + colorText.END)
print(colorText.BOLD + colorText.WARN + "[+] Download latest software from https://github.com/pranjal-joshi/Screeni-py/releases/latest" + colorText.END)
print(colorText.BOLD + colorText.WARN +
"\n[+] Developer: Pranjal Joshi." + colorText.END)
print(colorText.BOLD + colorText.WARN +
("[+] Version: %s" % VERSION) + colorText.END)
print(colorText.BOLD + colorText.WARN +
"[+] More: https://github.com/pranjal-joshi/Screeni-py" + colorText.END)
print(colorText.BOLD + colorText.WARN +
"[+] Post Feedback/Issues here: https://github.com/pranjal-joshi/Screeni-py/issues" + colorText.END)
print(colorText.BOLD + colorText.WARN +
"[+] Download latest software from https://github.com/pranjal-joshi/Screeni-py/releases/latest" + colorText.END)
input('')

# Save last screened result to pickle file
Expand All @@ -59,74 +66,99 @@ def setLastScreenedResults(df):
df.sort_values(by=['Stock'], ascending=True, inplace=True)
df.to_pickle(lastScreened)
except IOError:
input(colorText.BOLD + colorText.FAIL + '[+] Failed to save recently screened result table on disk! Skipping..' + colorText.END)
input(colorText.BOLD + colorText.FAIL +
'[+] Failed to save recently screened result table on disk! Skipping..' + colorText.END)

# Load last screened result to pickle file
def getLastScreenedResults():
try:
df = pd.read_pickle(lastScreened)
print(colorText.BOLD + colorText.GREEN + '\n[+] Showing recently screened results..\n' + colorText.END)
print(colorText.BOLD + colorText.GREEN +
'\n[+] Showing recently screened results..\n' + colorText.END)
print(tabulate(df, headers='keys', tablefmt='psql'))
print(colorText.BOLD + colorText.WARN + "[+] Note: Trend calculation is based on number of recent days to screen as per your configuration." + colorText.END)
input(colorText.BOLD + colorText.GREEN + '[+] Press any key to continue..' + colorText.END)
print(colorText.BOLD + colorText.WARN +
"[+] Note: Trend calculation is based on number of recent days to screen as per your configuration." + colorText.END)
input(colorText.BOLD + colorText.GREEN +
'[+] Press any key to continue..' + colorText.END)
except FileNotFoundError:
print(colorText.BOLD + colorText.FAIL + '[+] Failed to load recently screened result table from disk! Skipping..' + colorText.END)
print(colorText.BOLD + colorText.FAIL +
'[+] Failed to load recently screened result table from disk! Skipping..' + colorText.END)

def isTradingTime():
curr = datetime.datetime.now(pytz.timezone('Asia/Kolkata'))
openTime = curr.replace(hour=9, minute=15)
closeTime = curr.replace(hour=15, minute=30)
return ((openTime <= curr <= closeTime) and (0 <= curr.weekday() <= 4))


def saveStockData(stockDict, configManager, loadCount, screenCounter):
today_date = datetime.date.today().strftime("%d%m%y")
cache_file = "stock_data_" + str(today_date) + ".pkl"
weekday = datetime.date.today().weekday()
if weekday == 5 or weekday == 6:
last_friday = datetime.datetime.today() - datetime.timedelta(days=weekday - 4)
last_friday = last_friday.strftime("%d%m%y")
cache_file = "stock_data_" + str(last_friday) + ".pkl"
configManager.deleteStockData(excludeFile=cache_file)
if not os.path.exists(cache_file) or screenCounter > (loadCount+1):
with open(cache_file, 'wb') as f:
try:
pickle.dump(stockDict.copy(), f)
print(colorText.BOLD + colorText.GREEN + "=> Done." + colorText.END)
print(colorText.BOLD + colorText.GREEN +
"=> Done." + colorText.END)
except pickle.PicklingError:
print(colorText.BOLD + colorText.FAIL + "=> Error while Caching Stock Data." + colorText.END)
print(colorText.BOLD + colorText.FAIL +
"=> Error while Caching Stock Data." + colorText.END)
else:
print(colorText.BOLD + colorText.GREEN + "=> Already Cached." + colorText.END)
print(colorText.BOLD + colorText.GREEN +
"=> Already Cached." + colorText.END)

def loadStockData(stockDict):
today_date = datetime.date.today().strftime("%d%m%y")
cache_file = "stock_data_" + str(today_date) + ".pkl"
weekday = datetime.date.today().weekday()
if weekday == 5 or weekday == 6:
last_friday = datetime.datetime.today() - datetime.timedelta(days=weekday - 4)
last_friday = last_friday.strftime("%d%m%y")
cache_file = "stock_data_" + str(last_friday) + ".pkl"
if os.path.exists(cache_file):
with open(cache_file, 'rb') as f:
try:
stockData = pickle.load(f)
print(colorText.BOLD + colorText.GREEN + "[+] Automatically Using Cached Stock Data due to After-Market hours!" + colorText.END)
print(colorText.BOLD + colorText.GREEN +
"[+] Automatically Using Cached Stock Data due to After-Market hours!" + colorText.END)
for stock in stockData:
stockDict[stock] = stockData.get(stock)
except pickle.UnpicklingError:
print(colorText.BOLD + colorText.FAIL + "[+] Error while Reading Stock Cache." + colorText.END)
print(colorText.BOLD + colorText.FAIL +
"[+] Error while Reading Stock Cache." + colorText.END)
except EOFError:
print(colorText.BOLD + colorText.FAIL + "[+] Stock Cache Corrupted." + colorText.END)
print(colorText.BOLD + colorText.FAIL +
"[+] Stock Cache Corrupted." + colorText.END)
# Save screened results to excel

def promptSaveResults(df):
try:
response = str(input(colorText.BOLD + colorText.WARN + '[>] Do you want to save the results in excel file? [Y/N]: ')).upper()
response = str(input(colorText.BOLD + colorText.WARN +
'[>] Do you want to save the results in excel file? [Y/N]: ')).upper()
except ValueError:
response = 'Y'
if response != 'N':
filename = 'screenipy-result_'+datetime.datetime.now().strftime("%d-%m-%y_%H.%M.%S")+".xlsx"
filename = 'screenipy-result_' + \
datetime.datetime.now().strftime("%d-%m-%y_%H.%M.%S")+".xlsx"
df.to_excel(filename)
print(colorText.BOLD + colorText.GREEN + ("[+] Results saved to %s" % filename) + colorText.END)
print(colorText.BOLD + colorText.GREEN +
("[+] Results saved to %s" % filename) + colorText.END)

# Prompt for asking RSI
def promptRSIValues():
try:
minRSI, maxRSI = int(input(colorText.BOLD + colorText.WARN + "\n[+] Enter Min RSI value: " + colorText.END)), int(input(colorText.BOLD + colorText.WARN + "[+] Enter Max RSI value: " + colorText.END))
minRSI, maxRSI = int(input(colorText.BOLD + colorText.WARN + "\n[+] Enter Min RSI value: " + colorText.END)), int(
input(colorText.BOLD + colorText.WARN + "[+] Enter Max RSI value: " + colorText.END))
if (minRSI >= 0 and minRSI <= 100) and (maxRSI >= 0 and maxRSI <= 100) and (minRSI <= maxRSI):
return (minRSI, maxRSI)
raise ValueError
except ValueError:
return (0,0)
return (0, 0)

# Prompt for Reversal screening
def promptReversalScreening():
Expand All @@ -152,11 +184,13 @@ def promptChartPatterns():
0 > Cancel
[+] Select option: """ + colorText.END))
if resp == 1 or resp == 2:
candles = int(input(colorText.BOLD + colorText.WARN + "\n[+] How many candles (TimeFrame) to look back Inside Bar formation? : " + colorText.END))
candles = int(input(colorText.BOLD + colorText.WARN +
"\n[+] How many candles (TimeFrame) to look back Inside Bar formation? : " + colorText.END))
return (resp, candles)
if resp >= 0 and resp <= 2:
return resp
raise ValueError
except ValueError:
input(colorText.BOLD + colorText.FAIL + "\n[+] Invalid Option Selected. Press Any Key to Continue..." + colorText.END)
return (None, None)
input(colorText.BOLD + colorText.FAIL +
"\n[+] Invalid Option Selected. Press Any Key to Continue..." + colorText.END)
return (None, None)
9 changes: 5 additions & 4 deletions src/release.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@
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! :lipstick:
5. Cosmetic Updates - Progressbar for showing screening process! :lipstick:
6. Performance Upgrades! :gear:

## Downloads
* For :desktop_computer: **Windows** users, download **[screenipy.exe](https://github.com/pranjal-joshi/Screeni-py/releases/download/1.17/screenipy.exe)**
* For :penguin: **Linux** users, download **[screenipy.bin](https://github.com/pranjal-joshi/Screeni-py/releases/download/1.17/screenipy.bin)**
* For :apple: **MacOS** users, download **[screenipy.run](https://github.com/pranjal-joshi/Screeni-py/releases/download/1.17/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.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))

## How to use?

Expand Down
4 changes: 2 additions & 2 deletions src/screenipy.py
Original file line number Diff line number Diff line change
Expand Up @@ -269,14 +269,14 @@ def main(testing=False):
screenResults.rename(
columns={
'Trend': f'Trend ({configManager.daysToLookback}Days)',
'Breaking-Out': 'Breakout-Levels'
'Breaking-Out': f'Breakout ({configManager.daysToLookback}Days)'
},
inplace=True
)
saveResults.rename(
columns={
'Trend': f'Trend ({configManager.daysToLookback}Days)',
'Breaking-Out': 'Breakout-Levels'
'Breaking-Out': 'Breakout ({configManager.daysToLookback}Days)'
},
inplace=True
)
Expand Down

0 comments on commit 8974181

Please sign in to comment.