diff --git a/.github/dependencies/sqlite3.dll b/.github/dependencies/sqlite3.dll
new file mode 100644
index 00000000..e1230593
Binary files /dev/null and b/.github/dependencies/sqlite3.dll differ
diff --git a/.github/workflows/workflow-build-matrix.yml b/.github/workflows/workflow-build-matrix.yml
index 56d35732..6763eee7 100644
--- a/.github/workflows/workflow-build-matrix.yml
+++ b/.github/workflows/workflow-build-matrix.yml
@@ -24,7 +24,7 @@ jobs:
- os: windows-latest
TARGET: Windows
CMD_BUILD: |
- pyinstaller --onefile --icon=src\icon.ico src\screenipy.py --hidden-import cmath --hidden-import talib.stream --hidden-import numpy --hidden-import pandas --hidden-import alive-progress --hidden-import alive_progress
+ pyinstaller --onefile --icon=src\icon.ico src\screenipy.py --hidden-import cmath --hidden-import talib.stream --hidden-import numpy --hidden-import pandas --hidden-import alive-progress --hidden-import alive_progress --hidden-import chromadb
DEP_BUILD: |
python -m pip install --upgrade pip
echo Installing TA-lib...
@@ -44,7 +44,7 @@ jobs:
- os: ubuntu-20.04
TARGET: Linux
CMD_BUILD: |
- pyinstaller --onefile --icon=src/icon.ico src/screenipy.py --hidden-import cmath --hidden-import talib.stream --hidden-import numpy --hidden-import pandas --hidden-import alive-progress --hidden-import alive_progress
+ pyinstaller --onefile --icon=src/icon.ico src/screenipy.py --hidden-import cmath --hidden-import talib.stream --hidden-import numpy --hidden-import pandas --hidden-import alive-progress --hidden-import alive_progress --hidden-import chromadb
mv /home/runner/work/Screeni-py/Screeni-py/dist/screenipy /home/runner/work/Screeni-py/Screeni-py/dist/screenipy.bin
chmod +x /home/runner/work/Screeni-py/Screeni-py/dist/screenipy.bin
DEP_BUILD: |
@@ -68,7 +68,7 @@ jobs:
- os: macos-latest
TARGET: MacOS
CMD_BUILD: |
- pyinstaller --onefile --windowed --icon=src/icon.ico src/screenipy.py --hidden-import cmath --hidden-import talib.stream --hidden-import numpy --hidden-import pandas --hidden-import alive-progress --hidden-import alive_progress
+ pyinstaller --onefile --windowed --icon=src/icon.ico src/screenipy.py --hidden-import cmath --hidden-import talib.stream --hidden-import numpy --hidden-import pandas --hidden-import alive-progress --hidden-import alive_progress --hidden-import chromadb
mv /Users/runner/work/Screeni-py/Screeni-py/dist/screenipy /Users/runner/work/Screeni-py/Screeni-py/dist/screenipy.run
DEP_BUILD: |
brew install ta-lib
diff --git a/requirements.txt b/requirements.txt
index c852a3a9..b8521039 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -18,7 +18,7 @@ pyinstaller==5.6.2
pytest-mock
pytoml
retrying
-scipy==1.7.3
+scipy==1.11.2
ta-lib
tabulate
yfinance==0.1.87
@@ -61,4 +61,5 @@ pandas_ta
# protobuf==3.19.6
protobuf
streamlit==1.26.0
-tensorflow
\ No newline at end of file
+tensorflow
+chromadb==0.4.10
\ No newline at end of file
diff --git a/src/classes/Changelog.py b/src/classes/Changelog.py
index 88b02db4..e7f9ee0e 100644
--- a/src/classes/Changelog.py
+++ b/src/classes/Changelog.py
@@ -7,7 +7,7 @@
from classes.ColorText import colorText
-VERSION = "2.02"
+VERSION = "2.03"
changelog = colorText.BOLD + '[ChangeLog]\n' + colorText.END + colorText.BLUE + '''
[1.00 - Beta]
@@ -216,4 +216,8 @@
3. Cosmetic improvements
4. YouTube Video added to docs
+[2.03]
+1. AI based Nifty-50 Gap up/down prediction added to GUI
+2. Cosmetic updates and minor bug-fixes.
+
''' + colorText.END
diff --git a/src/classes/OtaUpdater.py b/src/classes/OtaUpdater.py
index 3dd1cfb1..3220e2ee 100644
--- a/src/classes/OtaUpdater.py
+++ b/src/classes/OtaUpdater.py
@@ -85,7 +85,8 @@ def showWhatsNew():
md = requests.get(url)
txt = md.text
txt = txt.split("New?")[1]
- txt = txt.split("## Downloads")[0]
+ # txt = txt.split("## Downloads")[0]
+ txt = txt.split("## Installation Guide")[0]
txt = txt.replace('**','').replace('`','').strip()
return (txt+"\n")
diff --git a/src/classes/ParallelProcessing.py b/src/classes/ParallelProcessing.py
index 54a94a26..6fdf7459 100644
--- a/src/classes/ParallelProcessing.py
+++ b/src/classes/ParallelProcessing.py
@@ -59,7 +59,7 @@ def run(self):
sys.exit(0)
def screenStocks(self, executeOption, reversalOption, maLength, daysForLowestVolume, minRSI, maxRSI, respChartPattern, insideBarToLookback, totalSymbols,
- configManager, fetcher, screener, candlePatterns, stock, newlyListedOnly, downloadOnly, printCounter=False):
+ configManager, fetcher, screener, candlePatterns, stock, newlyListedOnly, downloadOnly, vectorSearch, printCounter=False):
screenResults = pd.DataFrame(columns=[
'Stock', 'Consolidating', 'Breaking-Out', 'MA-Signal', 'Volume', 'LTP', 'RSI', 'Trend', 'Pattern'])
screeningDictionary = {'Stock': "", 'Consolidating': "", 'Breaking-Out': "",
@@ -105,6 +105,11 @@ def screenStocks(self, executeOption, reversalOption, maLength, daysForLowestVol
fullData, processedData = screener.preprocessData(
data, daysToLookback=configManager.daysToLookback)
+
+ if type(vectorSearch) != bool and type(vectorSearch) and vectorSearch[2] == True:
+ executeOption = 0
+ with self.screenCounter.get_lock():
+ screener.addVector(fullData, stock, vectorSearch[1])
if newlyListedOnly:
if not screener.validateNewlyListed(fullData, period):
diff --git a/src/classes/Screener.py b/src/classes/Screener.py
index 7dd242c3..ecc3830e 100644
--- a/src/classes/Screener.py
+++ b/src/classes/Screener.py
@@ -9,16 +9,22 @@
import math
import numpy as np
import pandas as pd
-# import talib
import joblib
import keras
+import time
import classes.Utility as Utility
+from classes.Utility import isGui
from sklearn.preprocessing import StandardScaler
from scipy.signal import argrelextrema
from scipy.stats import linregress
from classes.ColorText import colorText
from classes.SuppressOutput import SuppressOutput
from classes.ScreenipyTA import ScreenerTA
+try:
+ import chromadb
+ CHROMA_AVAILABLE = True
+except:
+ CHROMA_AVAILABLE = False
# Exception for newly listed stocks with candle nos < daysToLookback
@@ -592,9 +598,11 @@ def getNiftyPrediction(self, data, proxyServer):
out = colorText.BOLD + colorText.GREEN + "BULLISH" + colorText.END + colorText.BOLD
sug = "Stay Bullish!"
if not Utility.tools.isClosingHour():
- print(colorText.BOLD + colorText.WARN + "Note: The AI prediction should be executed After 3 PM or Near to Closing time as the Prediction Accuracy is based on the Closing price!" + colorText.END)
+ print(colorText.BOLD + colorText.WARN + "Note: The AI prediction should be executed After 3 PM Around the Closing hours as the Prediction Accuracy is based on the Closing price!" + colorText.END)
print(colorText.BOLD + colorText.BLUE + "\n" + "[+] Nifty AI Prediction -> " + colorText.END + colorText.BOLD + "Market may Open {} next day! {}".format(out, sug) + colorText.END)
print(colorText.BOLD + colorText.BLUE + "\n" + "[+] Nifty AI Prediction -> " + colorText.END + "Probability/Strength of Prediction = {}%".format(Utility.tools.getSigmoidConfidence(pred[0])))
+ if isGui():
+ return pred, 'BULLISH' if pred <= 0.5 else 'BEARISH', Utility.tools.getSigmoidConfidence(pred[0])
return pred
def monitorFiveEma(self, proxyServer, fetcher, result_df, last_signal, risk_reward = 3):
@@ -668,7 +676,27 @@ def monitorFiveEma(self, proxyServer, fetcher, result_df, last_signal, risk_rewa
result_df.drop_duplicates(keep='last', inplace=True)
result_df.sort_values(by='Time', inplace=True)
return result_df[::-1]
-
+
+ # Add data to vector database
+ def addVector(self, data, stockCode, daysToLookback):
+ data = data[::-1] # Reinverting preprocessedData for pct_change
+ data = data.pct_change()
+ # data = data[::-1] # Do we need to invert again? No we dont - See operation after flatten
+ data = data[['Open', 'High', 'Low', 'Close']]
+ data = data.reset_index(drop=True)
+ data = data.dropna()
+ data = data.to_numpy().flatten().tolist()
+ data = data[(-4 * daysToLookback):] # Keep only OHLC * daysToLookback samples
+ if len(data) == (4 * daysToLookback):
+ chroma_client = chromadb.PersistentClient(path="./chromadb_store/")
+ collection = chroma_client.get_or_create_collection(name="nse_stocks")
+ collection.upsert(
+ embeddings=[data],
+ documents=[stockCode],
+ ids=[stockCode]
+ )
+ return data
+
'''
# Find out trend for days to lookback
diff --git a/src/classes/Utility.py b/src/classes/Utility.py
index e037f910..42789412 100644
--- a/src/classes/Utility.py
+++ b/src/classes/Utility.py
@@ -286,6 +286,19 @@ def promptChartPatterns():
input(colorText.BOLD + colorText.FAIL +
"\n[+] Invalid Option Selected. Press Any Key to Continue..." + colorText.END)
return (None, None)
+
+ # Prompt for Similar stock search
+ def promptSimilarStockSearch():
+ try:
+ stockCode = str(input(colorText.BOLD + colorText.WARN +
+ "\n[+] Enter the Name of the stock to search similar stocks for: " + colorText.END)).upper()
+ candles = int(input(colorText.BOLD + colorText.WARN +
+ "\n[+] How many candles (TimeFrame) to look back for similarity? : " + colorText.END))
+ return stockCode, candles
+ except ValueError:
+ input(colorText.BOLD + colorText.FAIL +
+ "\n[+] Invalid Option Selected. Press Any Key to Continue..." + colorText.END)
+ return None, None
def getProgressbarStyle():
bar = 'smooth'
diff --git a/src/release.md b/src/release.md
index ef588070..2d85dbcb 100644
--- a/src/release.md
+++ b/src/release.md
@@ -16,12 +16,13 @@ Celebrating more than 7K+ Downloads - Thank You for your support :tada:
[![Screeni-py - Detailed Installation Guide](https://markdown-videos-api.jorgenkh.no/url?url=https%3A%2F%2Fyoutu.be%2F2HMN0ac4H20)](https://youtu.be/2HMN0ac4H20)
-## Downloads
+## Downloads
+#### Deprycated - Use Docker Method mentioned in next section
| Operating System | Executable File |
| :-: | --- |
-| ![Windows](https://img.shields.io/badge/Windows-0078D6?style=for-the-badge&logo=windows&logoColor=white) | **[screenipy.exe](https://github.com/pranjal-joshi/Screeni-py/releases/download/2.02/screenipy.exe)** |
-| ![Linux](https://img.shields.io/badge/Linux-FCC624?style=for-the-badge&logo=linux&logoColor=black) | **[screenipy.bin](https://github.com/pranjal-joshi/Screeni-py/releases/download/2.02/screenipy.bin)** |
-| ![Mac OS](https://img.shields.io/badge/mac%20os-D3D3D3?style=for-the-badge&logo=apple&logoColor=000000) | **[screenipy.run](https://github.com/pranjal-joshi/Screeni-py/releases/download/2.02/screenipy.run)** ([Read Installation Guide](https://github.com/pranjal-joshi/Screeni-py/blob/main/INSTALLATION.md#for-macos)) |
+| ![Windows](https://img.shields.io/badge/Windows-0078D6?style=for-the-badge&logo=windows&logoColor=white) | **[screenipy.exe](https://github.com/pranjal-joshi/Screeni-py/releases/download/2.03/screenipy.exe)** |
+| ![Linux](https://img.shields.io/badge/Linux-FCC624?style=for-the-badge&logo=linux&logoColor=black) | **[screenipy.bin](https://github.com/pranjal-joshi/Screeni-py/releases/download/2.03/screenipy.bin)** |
+| ![Mac OS](https://img.shields.io/badge/mac%20os-D3D3D3?style=for-the-badge&logo=apple&logoColor=000000) | **[screenipy.run](https://github.com/pranjal-joshi/Screeni-py/releases/download/2.03/screenipy.run)** ([Read Installation Guide](https://github.com/pranjal-joshi/Screeni-py/blob/main/INSTALLATION.md#for-macos)) |
## [Docker Releases](https://hub.docker.com/r/joshipranjal/screeni-py/tags)
diff --git a/src/screenipy.py b/src/screenipy.py
index f5d37031..c15d105f 100644
--- a/src/screenipy.py
+++ b/src/screenipy.py
@@ -1,7 +1,7 @@
#!/usr/bin/python3
-# Pyinstaller compile Windows: pyinstaller --onefile --icon=src\icon.ico src\screenipy.py --hidden-import cmath --hidden-import talib.stream --hidden-import numpy --hidden-import pandas --hidden-import alive-progress
-# Pyinstaller compile Linux : pyinstaller --onefile --icon=src/icon.ico src/screenipy.py --hidden-import cmath --hidden-import talib.stream --hidden-import numpy --hidden-import pandas --hidden-import alive-progress
+# Pyinstaller compile Windows: pyinstaller --onefile --icon=src\icon.ico src\screenipy.py --hidden-import cmath --hidden-import talib.stream --hidden-import numpy --hidden-import pandas --hidden-import alive-progress --hidden-import chromadb
+# Pyinstaller compile Linux : pyinstaller --onefile --icon=src/icon.ico src/screenipy.py --hidden-import cmath --hidden-import talib.stream --hidden-import numpy --hidden-import pandas --hidden-import alive-progress --hidden-import chromadb
# Keep module imports prior to classes
import os
@@ -28,6 +28,11 @@
from tabulate import tabulate
import multiprocessing
multiprocessing.freeze_support()
+try:
+ import chromadb
+ CHROMA_AVAILABLE = True
+except:
+ CHROMA_AVAILABLE = False
# Argument Parsing for test purpose
argParser = argparse.ArgumentParser()
@@ -51,6 +56,9 @@
loadCount = 0
maLength = None
newlyListedOnly = False
+vectorSearch = False
+
+CHROMADB_PATH = "chromadb_store/"
configManager = ConfigManager.tools()
fetcher = Fetcher.tools(configManager)
@@ -63,6 +71,15 @@
except KeyError:
proxyServer = ""
+# Clear chromadb store initially
+if CHROMA_AVAILABLE:
+ chroma_client = chromadb.PersistentClient(path=CHROMADB_PATH)
+ try:
+ chroma_client.delete_collection("nse_stocks")
+ except:
+ pass
+
+
# Manage Execution flow
@@ -74,6 +91,7 @@ def initExecution():
W > Screen stocks from my own Watchlist
N > Nifty Prediction using Artifical Intelligence (Use for Gap-Up/Gap-Down/BTST/STBT)
E > Live Index Scan : 5 EMA for Intraday
+ S > Search for Similar Stocks (forming Similar Chart Pattern)
0 > Screen stocks by the stock names (NSE Stock Code)
1 > Nifty 50 2 > Nifty Next 50 3 > Nifty 100
@@ -108,7 +126,7 @@ def initExecution():
Utility.tools.clearScreen()
return initExecution()
- if tickerOption == 'N' or tickerOption == 'E':
+ if tickerOption == 'N' or tickerOption == 'E' or tickerOption == 'S':
return tickerOption, 0
if tickerOption and tickerOption != 'W':
@@ -153,7 +171,7 @@ def initExecution():
# Main function
def main(testing=False, testBuild=False, downloadOnly=False, execute_inputs:list = []):
- global screenCounter, screenResultsCounter, stockDict, loadedStockData, keyboardInterruptEvent, loadCount, maLength, newlyListedOnly
+ global screenCounter, screenResultsCounter, stockDict, loadedStockData, keyboardInterruptEvent, loadCount, maLength, newlyListedOnly, vectorSearch
screenCounter = multiprocessing.Value('i', 1)
screenResultsCounter = multiprocessing.Value('i', 0)
keyboardInterruptEvent = multiprocessing.Manager().Event()
@@ -184,7 +202,10 @@ def main(testing=False, testBuild=False, downloadOnly=False, execute_inputs:list
if execute_inputs != []:
if not configManager.checkConfigFile():
configManager.setConfig(ConfigManager.parser, default=True, showFileCreatedText=False)
- tickerOption, executeOption = int(execute_inputs[0]), int(execute_inputs[1])
+ try:
+ tickerOption, executeOption = int(execute_inputs[0]), int(execute_inputs[1])
+ except:
+ tickerOption, executeOption = str(execute_inputs[0]), int(execute_inputs[1])
if tickerOption == 13:
newlyListedOnly = True
tickerOption = 12
@@ -268,7 +289,7 @@ def main(testing=False, testBuild=False, downloadOnly=False, execute_inputs:list
"[+] Press any key to Exit!" + colorText.END)
sys.exit(0)
- if tickerOption == 'W' or tickerOption == 'N' or tickerOption == 'E' or (tickerOption >= 0 and tickerOption < 15):
+ if tickerOption == 'W' or tickerOption == 'N' or tickerOption == 'E' or tickerOption == 'S' or (tickerOption >= 0 and tickerOption < 15):
configManager.getConfig(ConfigManager.parser)
try:
if tickerOption == 'W':
@@ -316,6 +337,18 @@ def main(testing=False, testBuild=False, downloadOnly=False, execute_inputs:list
if not isGui():
input('\nPress any key to Continue...\n')
return
+ elif tickerOption == 'S':
+ if not CHROMA_AVAILABLE:
+ print(colorText.BOLD + colorText.FAIL +
+ "\n\n[+] ChromaDB not available in your environment! You can't use this feature!\n" + colorText.END)
+ else:
+ if execute_inputs != []:
+ stockCode, candles = execute_inputs[2], execute_inputs[3]
+ else:
+ stockCode, candles = Utility.tools.promptSimilarStockSearch()
+ vectorSearch = [stockCode, candles, True]
+ tickerOption, executeOption = 12, 1
+ listStockCodes = fetcher.fetchStockCodes(tickerOption, proxyServer=proxyServer)
else:
if tickerOption == 14: # Override config for F&O Stocks
configManager.stageTwo = False
@@ -338,7 +371,7 @@ def main(testing=False, testBuild=False, downloadOnly=False, execute_inputs:list
"[+] Starting Stock Screening.. Press Ctrl+C to stop!\n")
items = [(executeOption, reversalOption, maLength, daysForLowestVolume, minRSI, maxRSI, respChartPattern, insideBarToLookback, len(listStockCodes),
- configManager, fetcher, screener, candlePatterns, stock, newlyListedOnly, downloadOnly)
+ configManager, fetcher, screener, candlePatterns, stock, newlyListedOnly, downloadOnly, vectorSearch)
for stock in listStockCodes]
tasks_queue = multiprocessing.JoinableQueue()
@@ -416,6 +449,25 @@ def main(testing=False, testBuild=False, downloadOnly=False, execute_inputs:list
except Exception as e:
break
+ if CHROMA_AVAILABLE and type(vectorSearch) == list and vectorSearch[2]:
+ chroma_client = chromadb.PersistentClient(path=CHROMADB_PATH)
+ collection = chroma_client.get_collection(name="nse_stocks")
+ query_embeddings= collection.get(ids = [stockCode], include=["embeddings"])["embeddings"]
+ results = collection.query(
+ query_embeddings=query_embeddings,
+ n_results=4
+ )['ids'][0]
+ try:
+ results.remove(stockCode)
+ except ValueError:
+ pass
+ matchedScreenResults, matchedSaveResults = pd.DataFrame(columns=screenResults.columns), pd.DataFrame(columns=saveResults.columns)
+ for stk in results:
+ matchedScreenResults = matchedScreenResults.append(screenResults[screenResults['Stock'].str.contains(stk)])
+ matchedSaveResults = matchedSaveResults.append(saveResults[saveResults['Stock'].str.contains(stk)])
+ screenResults, saveResults = matchedScreenResults, matchedSaveResults
+
+
screenResults.sort_values(by=['Stock'], ascending=True, inplace=True)
saveResults.sort_values(by=['Stock'], ascending=True, inplace=True)
screenResults.set_index('Stock', inplace=True)
@@ -456,6 +508,7 @@ def main(testing=False, testBuild=False, downloadOnly=False, execute_inputs:list
if not isGui():
input('')
newlyListedOnly = False
+ vectorSearch = False
if __name__ == "__main__":
@@ -474,7 +527,7 @@ def main(testing=False, testBuild=False, downloadOnly=False, execute_inputs:list
while True:
main()
except Exception as e:
- # raise e
+ raise e
if isDevVersion == OTAUpdater.developmentVersion:
raise(e)
input(colorText.BOLD + colorText.FAIL +
diff --git a/src/streamlit_app.py b/src/streamlit_app.py
index 8ba42d07..d1ce7f42 100644
--- a/src/streamlit_app.py
+++ b/src/streamlit_app.py
@@ -31,6 +31,23 @@
execute_inputs = []
+def show_df_as_result_table():
+ try:
+ df = pd.read_pickle('last_screened_unformatted_results.pkl')
+ st.markdown(f'#### 🔍 Found {len(df)} Results')
+ df.index = df.index.map(lambda x: "https://in.tradingview.com/chart?symbol=NSE%3A" + x)
+ df.index = df.index.map(lambda x: f'{x.split("%3A")[-1]}')
+ df['Stock'] = df.index
+ stock_column = df.pop('Stock') # Remove 'Age' column and store it separately
+ df.insert(0, 'Stock', stock_column)
+ st.write(df.to_html(escape=False, index=False, index_names=False), unsafe_allow_html=True)
+ st.write(' ')
+ except FileNotFoundError:
+ st.error('Last Screened results are not available at the moment')
+ except Exception as e:
+ st.error('No Dataframe found for last_screened_results.pkl')
+ st.exception(e)
+
def on_config_change():
configManager = ConfigManager.tools()
configManager.period = period
@@ -55,6 +72,40 @@ def on_start_button_click():
except StopIteration:
pass
+def nifty_predict(col):
+ with col.container():
+ with st.spinner('🔮 Taking a Look into the Future, Please wait...'):
+ import classes.Fetcher as Fetcher
+ import classes.Screener as Screener
+ configManager = ConfigManager.tools()
+ fetcher = Fetcher.tools(configManager)
+ screener = Screener.tools(configManager)
+ os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'
+ prediction, trend, confidence = screener.getNiftyPrediction(
+ data=fetcher.fetchLatestNiftyDaily(proxyServer=proxyServer),
+ proxyServer=proxyServer
+ )
+ if 'BULLISH' in trend:
+ col.success(f'Market may Open **Gap Up** next day!\n\nProbability/Strength of Prediction = {confidence}%', icon='📈')
+ elif 'BEARISH' in trend:
+ col.error(f'Market may Open **Gap Down** next day!\n\nProbability/Strength of Prediction = {confidence}%', icon='📉')
+ else:
+ col.info("Couldn't determine the Trend. Try again later!")
+ col.warning('The AI prediction should be executed After 3 PM or Around the Closing hours as the Prediction Accuracy is based on the Closing price!\n\nThis is Just a Statistical Prediction and There are Chances of **False** Predictions!', icon='⚠️')
+
+def find_similar_stocks(stockCode:str, candles:int):
+ global execute_inputs
+ stockCode = stockCode.upper()
+ if ',' in stockCode or ' ' in stockCode or stockCode == '':
+ st.error('Invalid Character in Stock Name!', icon='😾')
+ return False
+ else:
+ execute_inputs = ['S', 0, stockCode, candles, 'N']
+ on_start_button_click()
+ st.toast('Screening Completed!', icon='🎉')
+ sleep(2)
+ return True
+
def get_extra_inputs(tickerOption, executeOption, c_index=None, c_criteria=None, start_button=None):
global execute_inputs
if not tickerOption.isnumeric():
@@ -135,7 +186,7 @@ def get_extra_inputs(tickerOption, executeOption, c_index=None, c_criteria=None,
bc.divider()
bc.image(telegram_url, width=96)
-tab_screen, tab_config, tab_about = st.tabs(['Screen Stocks', 'Configuration', 'About'])
+tab_screen, tab_similar, tab_nifty, tab_config, tab_about = st.tabs(['Screen Stocks', 'Search Similar Stocks', 'Nifty-50 Gap Prediction', 'Configuration', 'About'])
with tab_screen:
st.markdown("""
@@ -265,28 +316,15 @@ def get_extra_inputs(tickerOption, executeOption, c_index=None, c_criteria=None,
sleep(2)
with st.container():
- try:
- df = pd.read_pickle('last_screened_unformatted_results.pkl')
- st.markdown(f'#### Found {len(df)} Results')
- df.index = df.index.map(lambda x: "https://in.tradingview.com/chart?symbol=NSE%3A" + x)
- df.index = df.index.map(lambda x: f'{x.split("%3A")[-1]}')
- df['Stock'] = df.index
- stock_column = df.pop('Stock') # Remove 'Age' column and store it separately
- df.insert(0, 'Stock', stock_column)
- st.write(df.to_html(escape=False, index=False, index_names=False), unsafe_allow_html=True)
- st.write(' ')
- except FileNotFoundError:
- st.error('Last Screened results are not available at the moment')
- except Exception as e:
- st.error('No Dataframe found for last_screened_results.pkl')
- st.exception(e)
+ show_df_as_result_table()
+
with tab_config:
configManager = ConfigManager.tools()
configManager.getConfig(parser=ConfigManager.parser)
ac, bc = st.columns([10,2])
- ac.markdown('### Screening Configuration')
+ ac.markdown('### 🔧 Screening Configuration')
bc.download_button(
label="Export Configuration",
data=Path('screenipy.ini').read_text(),
@@ -327,6 +365,27 @@ def get_extra_inputs(tickerOption, executeOption, c_index=None, c_criteria=None,
f.write(bytes_data)
st.toast('Configuration Imported', icon='⚙️')
+with tab_nifty:
+ ac, bc = st.columns([9,1])
+
+ ac.subheader('🧠 AI-based prediction for Next Day Nifty-50 Gap Up / Gap Down')
+ bc.button('**Predict**', type='primary', on_click=nifty_predict, args=(ac,), use_container_width=True)
+
+with tab_similar:
+
+ st.subheader('🕵🏻 Find Stocks forming Similar Chart Patterns')
+ ac, bc, cc = st.columns([4,2,1])
+
+ stockCode = ac.text_input('Enter Stock Name and Press Enter', placeholder='HDFCBANK')
+ candles = bc.number_input('Lookback Period (No. of Candles)', min_value=1, step=1, value=int(configManager.daysToLookback))
+ similar_search_button = cc.button('**Search**', type='primary', use_container_width=True)
+
+ if similar_search_button:
+ result = find_similar_stocks(stockCode, candles)
+ if result:
+ with st.container():
+ show_df_as_result_table()
+
with tab_about:
from classes.Changelog import VERSION, changelog