pkscreener 0.46.20250810.756__cp312-cp312-manylinux2014_x86_64.whl → 0.46.20250908.764__cp312-cp312-manylinux2014_x86_64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/LICENSE-Others.txt +1 -1
- {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/README.txt +6 -6
- {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/__init__.py +2 -2
- {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/AssetsManager.py +13 -29
- {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/Backtest.py +5 -5
- {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/CandlePatterns.py +23 -23
- {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/ConfigManager.py +13 -1
- {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/ConsoleUtility.py +1 -1
- {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/Fetcher.py +26 -20
- {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/ImageUtility.py +1 -1
- {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/MarketMonitor.py +6 -6
- {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/MarketStatus.py +3 -2
- {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/PKMarketOpenCloseAnalyser.py +14 -14
- {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/PKScanRunner.py +2 -2
- {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/Pktalib.py +36 -36
- {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/PortfolioXRay.py +5 -5
- {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/ScreeningStatistics.py +457 -445
- {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/StockScreener.py +47 -34
- {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/Utility.py +4 -3
- pkscreener-0.46.20250908.764.data/purelib/pkscreener/classes/__init__.py +1 -0
- {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/globals.py +25 -23
- {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/pkscreenerbot.py +1 -0
- {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/pkscreenercli.py +9 -9
- {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/requirements.txt +3 -3
- {pkscreener-0.46.20250810.756.dist-info → pkscreener-0.46.20250908.764.dist-info}/METADATA +10 -11
- pkscreener-0.46.20250908.764.dist-info/RECORD +58 -0
- pkscreener-0.46.20250810.756.data/purelib/pkscreener/classes/__init__.py +0 -1
- pkscreener-0.46.20250810.756.dist-info/RECORD +0 -58
- {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/Disclaimer.txt +0 -0
- {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/LICENSE.txt +0 -0
- {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/LogoWM.txt +0 -0
- {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/ArtTexts.py +0 -0
- {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/Barometer.py +0 -0
- {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/BaseScreeningStatistics.py +0 -0
- {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/Changelog.py +0 -0
- {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/ConsoleMenuUtility.py +0 -0
- {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/GlobalStore.py +0 -0
- {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/MenuOptions.py +0 -0
- {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/Messenger.py +0 -0
- {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/OtaUpdater.py +0 -0
- {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/PKAnalytics.py +0 -0
- {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/PKDataService.py +0 -0
- {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/PKDemoHandler.py +0 -0
- {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/PKPremiumHandler.py +0 -0
- {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/PKScheduledTaskProgress.py +0 -0
- {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/PKScheduler.py +0 -0
- {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/PKSpreadsheets.py +0 -0
- {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/PKTask.py +0 -0
- {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/PKUserRegistration.py +0 -0
- {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/Portfolio.py +0 -0
- {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/StockSentiment.py +0 -0
- {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/UserMenuChoicesHandler.py +0 -0
- {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/WorkflowManager.py +0 -0
- {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/keys.py +0 -0
- {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/courbd.ttf +0 -0
- {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/pkscreener.ini +0 -0
- {pkscreener-0.46.20250810.756.dist-info → pkscreener-0.46.20250908.764.dist-info}/WHEEL +0 -0
- {pkscreener-0.46.20250810.756.dist-info → pkscreener-0.46.20250908.764.dist-info}/entry_points.txt +0 -0
- {pkscreener-0.46.20250810.756.dist-info → pkscreener-0.46.20250908.764.dist-info}/licenses/LICENSE +0 -0
- {pkscreener-0.46.20250810.756.dist-info → pkscreener-0.46.20250908.764.dist-info}/top_level.txt +0 -0
@@ -35,7 +35,7 @@ warnings.simplefilter("ignore", FutureWarning)
|
|
35
35
|
import pandas as pd
|
36
36
|
# from PKDevTools.classes.log import tracelog
|
37
37
|
# from PKDevTools.classes.PKTimer import PKTimer
|
38
|
-
from PKDevTools.classes import Archiver
|
38
|
+
from PKDevTools.classes import Archiver, log
|
39
39
|
from PKDevTools.classes.ColorText import colorText
|
40
40
|
from PKDevTools.classes.Fetcher import StockDataEmptyException
|
41
41
|
from PKDevTools.classes.SuppressOutput import SuppressOutput
|
@@ -51,6 +51,17 @@ class StockScreener:
|
|
51
51
|
self.isTradingTime = PKDateUtilities.isTradingTime()
|
52
52
|
self.configManager = None
|
53
53
|
|
54
|
+
def setupLogger(self, log_level):
|
55
|
+
if log_level > 0:
|
56
|
+
os.environ["PKDevTools_Default_Log_Level"] = str(log_level)
|
57
|
+
log.setup_custom_logger(
|
58
|
+
"pkscreener",
|
59
|
+
log_level,
|
60
|
+
trace=False,
|
61
|
+
log_file_path="pkscreener-logs.txt",
|
62
|
+
filter=None,
|
63
|
+
)
|
64
|
+
|
54
65
|
# @tracelog
|
55
66
|
def screenStocks(
|
56
67
|
self,
|
@@ -85,6 +96,7 @@ class StockScreener:
|
|
85
96
|
), "hostRef argument must not be None. It should be an instance of PKMultiProcessorClient"
|
86
97
|
if stock is None or len(stock) == 0:
|
87
98
|
return None
|
99
|
+
self.setupLogger(log_level=logLevel)
|
88
100
|
configManager = hostRef.configManager
|
89
101
|
self.configManager = configManager
|
90
102
|
screeningDictionary, saveDictionary = self.initResultDictionaries()
|
@@ -480,7 +492,7 @@ class StockScreener:
|
|
480
492
|
# Must-run, but only at the end
|
481
493
|
try:
|
482
494
|
if executeOption != 7 or (executeOption == 7 and respChartPattern != 7):
|
483
|
-
# Only 'doji' and 'inside' is internally implemented by
|
495
|
+
# Only 'doji' and 'inside' is internally implemented by pandas_ta_classic.
|
484
496
|
# Otherwise, for the rest of the candle patterns, they also need
|
485
497
|
# TA-Lib. So if TA-Lib is not available, it will throw exception
|
486
498
|
# We can live with no-patterns if user has not installed ta-lib
|
@@ -682,7 +694,7 @@ class StockScreener:
|
|
682
694
|
screener.validateCCI(
|
683
695
|
processedData, screeningDictionary, saveDictionary, minRSI, maxRSI
|
684
696
|
)
|
685
|
-
if isNotMonitoringDashboard and executeOption != 21 and backtestDuration == 0:
|
697
|
+
if configManager.enableAdditionalTrendFilters and isNotMonitoringDashboard and executeOption != 21 and backtestDuration == 0:
|
686
698
|
# We don't need to have MFI or fair value data for backtesting because those
|
687
699
|
# are anyways only available for days in the past.
|
688
700
|
# For executeOption 21, we'd have already got the mfiStake and fairValueDiff
|
@@ -719,28 +731,28 @@ class StockScreener:
|
|
719
731
|
# Capturing Ctr+C Here isn't a great idea
|
720
732
|
pass
|
721
733
|
except StockDataEmptyException as e: # pragma: no cover
|
722
|
-
|
723
|
-
|
734
|
+
if data is None or (data is not None and not data.isnull().values.all(axis=0)[0]):
|
735
|
+
hostRef.default_logger.debug(f"StockDataEmptyException:{stock}: {e}", exc_info=True)
|
724
736
|
pass
|
725
737
|
except ScreeningStatistics.EligibilityConditionNotMet as e: # pragma: no cover
|
726
|
-
|
727
|
-
|
738
|
+
if userArgsLog:
|
739
|
+
hostRef.default_logger.debug(f"EligibilityConditionNotMet:{stock}: {e}", exc_info=True)
|
728
740
|
pass
|
729
741
|
except ScreeningStatistics.NotNewlyListed as e: # pragma: no cover
|
730
|
-
|
731
|
-
|
742
|
+
if userArgsLog:
|
743
|
+
hostRef.default_logger.debug(f"NotNewlyListed:{stock}: {e}", exc_info=True)
|
732
744
|
pass
|
733
745
|
except ScreeningStatistics.NotAStageTwoStock as e: # pragma: no cover
|
734
|
-
|
735
|
-
|
746
|
+
if userArgsLog:
|
747
|
+
hostRef.default_logger.debug(f"NotAStageTwoStock:{stock}: {e}", exc_info=True)
|
736
748
|
pass
|
737
749
|
except ScreeningStatistics.NotEnoughVolumeAsPerConfig as e: # pragma: no cover
|
738
|
-
|
739
|
-
|
750
|
+
if userArgsLog:
|
751
|
+
hostRef.default_logger.debug(f"NotEnoughVolumeAsPerConfig:{stock}: {e}", exc_info=True)
|
740
752
|
pass
|
741
753
|
except ScreeningStatistics.DownloadDataOnly as e: # pragma: no cover
|
742
|
-
|
743
|
-
|
754
|
+
if userArgsLog:
|
755
|
+
hostRef.default_logger.debug(f"DownloadDataOnly:{stock}: {e}", exc_info=True)
|
744
756
|
try:
|
745
757
|
data = hostRef.objectDictionaryPrimary.get(stock)
|
746
758
|
if data is not None:
|
@@ -750,7 +762,7 @@ class StockScreener:
|
|
750
762
|
except KeyboardInterrupt: # pragma: no cover
|
751
763
|
raise KeyboardInterrupt
|
752
764
|
except Exception as ex:
|
753
|
-
|
765
|
+
hostRef.default_logger.debug(f"MFIStatus: {stock}:\n{ex}", exc_info=True)
|
754
766
|
pass
|
755
767
|
try:
|
756
768
|
screener.getFairValue(stock,hostData=data, force=True,exchangeName=exchangeName)
|
@@ -758,24 +770,24 @@ class StockScreener:
|
|
758
770
|
except KeyboardInterrupt: # pragma: no cover
|
759
771
|
raise KeyboardInterrupt
|
760
772
|
except Exception as ex:
|
761
|
-
|
773
|
+
hostRef.default_logger.debug(f"FairValue: {stock}:\n{ex}", exc_info=True)
|
762
774
|
pass
|
763
775
|
pass
|
764
776
|
except ScreeningStatistics.LTPNotInConfiguredRange as e: # pragma: no cover
|
765
|
-
|
766
|
-
|
777
|
+
if userArgsLog:
|
778
|
+
hostRef.default_logger.debug(f"LTPNotInConfiguredRange:{stock}: {e}", exc_info=True)
|
767
779
|
pass
|
768
780
|
except KeyError as e: # pragma: no cover
|
769
|
-
|
770
|
-
|
781
|
+
if userArgsLog:
|
782
|
+
hostRef.default_logger.debug(f"KeyError:{stock}: {e}", exc_info=True)
|
771
783
|
pass
|
772
784
|
except OSError as e: # pragma: no cover
|
773
|
-
|
774
|
-
|
785
|
+
if userArgsLog:
|
786
|
+
hostRef.default_logger.debug(f"OSError:{stock}: {e}", exc_info=True)
|
775
787
|
pass
|
776
788
|
except Exception as e: # pragma: no cover
|
777
|
-
|
778
|
-
|
789
|
+
if userArgsLog:
|
790
|
+
hostRef.default_logger.debug(f"Exception:{stock}: {e}", exc_info=True)
|
779
791
|
if testbuild or printCounter:
|
780
792
|
import traceback
|
781
793
|
traceback.print_exc()
|
@@ -905,19 +917,19 @@ class StockScreener:
|
|
905
917
|
fullData = None
|
906
918
|
processedData = None
|
907
919
|
ohlc_dict = {
|
908
|
-
|
909
|
-
|
910
|
-
|
911
|
-
|
920
|
+
"open":'first',
|
921
|
+
"high":'max',
|
922
|
+
"low":'min',
|
923
|
+
"close":'last',
|
912
924
|
'Adj Close': 'last',
|
913
|
-
|
925
|
+
"volume":'sum'
|
914
926
|
}
|
915
927
|
candleDuration = self.configManager.candleDurationInt
|
916
928
|
candleDurationFrequency = self.configManager.candleDurationFrequency
|
917
929
|
durationFrequency = "T" if candleDurationFrequency=="m" else ("H" if candleDurationFrequency=="h" else ("M" if candleDurationFrequency=="mo" else ("W" if candleDurationFrequency=="wk" else "T")))
|
918
930
|
if int(candleDuration) >= 1 and (candleDurationFrequency in ["m","h","mo","wk"]):
|
919
931
|
data = data.resample(f'{candleDuration}{durationFrequency}', offset='15min').agg(ohlc_dict)
|
920
|
-
data = data[data["
|
932
|
+
data = data[data["high"]>0] # resampling can introduce 0 value rows for non-market hours
|
921
933
|
if backtestDuration == 0:
|
922
934
|
fullData, processedData = screener.preprocessData(
|
923
935
|
data, daysToLookback=configManager.effectiveDaysToLookback
|
@@ -1049,6 +1061,7 @@ class StockScreener:
|
|
1049
1061
|
else:
|
1050
1062
|
data.rename(columns={"index": "Date"}, inplace=True)
|
1051
1063
|
data.set_index("Date", inplace=True)
|
1064
|
+
data.index = pd.to_datetime(data.index)
|
1052
1065
|
except: # pragma: no cover
|
1053
1066
|
pass
|
1054
1067
|
if ((shouldCache and not self.isTradingTime and (hostData is None or hostDataLength == 0)) or downloadOnly) \
|
@@ -1130,7 +1143,7 @@ class StockScreener:
|
|
1130
1143
|
"52Wk-L",
|
1131
1144
|
"RSI",
|
1132
1145
|
"RSIi",
|
1133
|
-
"
|
1146
|
+
"volume",
|
1134
1147
|
"22-Pd",
|
1135
1148
|
"Consol.",
|
1136
1149
|
"Breakout",
|
@@ -1148,7 +1161,7 @@ class StockScreener:
|
|
1148
1161
|
"52Wk-L": 0,
|
1149
1162
|
"RSI": 0,
|
1150
1163
|
"RSIi": 0,
|
1151
|
-
"
|
1164
|
+
"volume": "",
|
1152
1165
|
"22-Pd": "",
|
1153
1166
|
"Consol.": "Range:0%",
|
1154
1167
|
"Breakout": "BO: 0 R: 0",
|
@@ -1166,7 +1179,7 @@ class StockScreener:
|
|
1166
1179
|
"52Wk-L": 0,
|
1167
1180
|
"RSI": 0,
|
1168
1181
|
"RSIi": 0,
|
1169
|
-
"
|
1182
|
+
"volume": "",
|
1170
1183
|
"22-Pd": "",
|
1171
1184
|
"Consol.": "Range:0%",
|
1172
1185
|
"Breakout": "BO: 0 R: 0",
|
@@ -73,6 +73,7 @@ artText = f"{getArtText()}\n"
|
|
73
73
|
STD_ENCODING=sys.stdout.encoding if sys.stdout is not None else 'utf-8'
|
74
74
|
|
75
75
|
def marketStatus():
|
76
|
+
return "NA"
|
76
77
|
# task = PKTask("Nifty 50 Market Status",MarketStatus().getMarketStatus)
|
77
78
|
lngStatus = MarketStatus().marketStatus
|
78
79
|
nseStatus = ""
|
@@ -85,8 +86,8 @@ def marketStatus():
|
|
85
86
|
# scheduleTasks(tasksList=[task])
|
86
87
|
if lngStatus == "":
|
87
88
|
lngStatus = MarketStatus().getMarketStatus(exchangeSymbol="^IXIC" if configManager.defaultIndex == 15 else "^NSEI")
|
88
|
-
if "
|
89
|
-
lngStatus = lngStatus.replace("Closed","
|
89
|
+
if "close" in lngStatus and nseStatus == "open":
|
90
|
+
lngStatus = lngStatus.replace("Closed","open")
|
90
91
|
if len(next_bell) > 0 and next_bell not in lngStatus:
|
91
92
|
lngStatus = f"{lngStatus} | Next Bell: {colorText.WARN}{next_bell.replace('T',' ').split('+')[0]}{colorText.END}"
|
92
93
|
return (lngStatus +"\n") if lngStatus is not None else "\n"
|
@@ -141,7 +142,7 @@ class tools:
|
|
141
142
|
pass
|
142
143
|
|
143
144
|
@Halo(text='', spinner='dots')
|
144
|
-
def tryFetchFromServer(cache_file,repoOwner="pkjmesra",repoName="PKScreener",directory="
|
145
|
+
def tryFetchFromServer(cache_file,repoOwner="pkjmesra",repoName="PKScreener",directory="results/Data",hideOutput=False,branchName="refs/heads/actions-data-download"):
|
145
146
|
if not hideOutput:
|
146
147
|
OutputControls().printOutput(
|
147
148
|
colorText.FAIL
|
@@ -0,0 +1 @@
|
|
1
|
+
VERSION='0.46.20250908.764'
|
@@ -320,7 +320,7 @@ def getSummaryCorrectnessOfStrategy(resultdf, summaryRequired=True):
|
|
320
320
|
)
|
321
321
|
)
|
322
322
|
detaildf = detaildf.replace(np.nan, "", regex=True)
|
323
|
-
detaildf.loc[:, "
|
323
|
+
detaildf.loc[:, "volume"] = detaildf.loc[:, "volume"].apply(
|
324
324
|
lambda x: Utility.tools.formatRatio(x, configManager.volumeRatio)
|
325
325
|
)
|
326
326
|
detaildf.sort_values(
|
@@ -754,7 +754,7 @@ def labelDataForPrinting(screenResults, saveResults, configManager, volumeRatio,
|
|
754
754
|
saveResults['RSI'] = saveResults['RSI'].astype(str) + "/" + saveResults['RSIi'].astype(str)
|
755
755
|
screenResults.rename(columns={"RSI": "RSI/i"},inplace=True)
|
756
756
|
saveResults.rename(columns={"RSI": "RSI/i"},inplace=True)
|
757
|
-
sortKey = ["
|
757
|
+
sortKey = ["volume"] if "RSI" not in menuChoiceHierarchy else ("RSIi" if (isTrading or "RSIi" in saveResults.columns) else "RSI")
|
758
758
|
ascending = [False if "RSI" not in menuChoiceHierarchy else True]
|
759
759
|
if executeOption == 21:
|
760
760
|
if reversalOption in [3,5,6,7]:
|
@@ -769,20 +769,20 @@ def labelDataForPrinting(screenResults, saveResults, configManager, volumeRatio,
|
|
769
769
|
sortKey = ["SuperConfSort"]
|
770
770
|
ascending = [False]
|
771
771
|
else:
|
772
|
-
sortKey = ["
|
772
|
+
sortKey = ["volume"]
|
773
773
|
ascending = [False]
|
774
774
|
elif reversalOption in [4]:
|
775
775
|
if "deviationScore" in saveResults.columns:
|
776
776
|
sortKey = ["deviationScore"]
|
777
777
|
ascending = [True]
|
778
778
|
else:
|
779
|
-
sortKey = ["
|
779
|
+
sortKey = ["volume"]
|
780
780
|
ascending = [False]
|
781
781
|
elif executeOption == 23:
|
782
|
-
sortKey = ["bbands_ulr_ratio_max5"] if "bbands_ulr_ratio_max5" in screenResults.columns else ["
|
782
|
+
sortKey = ["bbands_ulr_ratio_max5"] if "bbands_ulr_ratio_max5" in screenResults.columns else ["volume"]
|
783
783
|
ascending = [False]
|
784
784
|
elif executeOption == 27: # ATR Cross
|
785
|
-
sortKey = ["ATR"] if "ATR" in screenResults.columns else ["
|
785
|
+
sortKey = ["ATR"] if "ATR" in screenResults.columns else ["volume"]
|
786
786
|
ascending = [False]
|
787
787
|
elif executeOption == 31: # DEEL Momentum
|
788
788
|
sortKey = ["%Chng"]
|
@@ -824,12 +824,12 @@ def labelDataForPrinting(screenResults, saveResults, configManager, volumeRatio,
|
|
824
824
|
screenResults.set_index("Stock", inplace=True)
|
825
825
|
if "Stock" in saveResults.columns:
|
826
826
|
saveResults.set_index("Stock", inplace=True)
|
827
|
-
screenResults[
|
828
|
-
saveResults[
|
829
|
-
screenResults.loc[:, "
|
827
|
+
screenResults["volume"] = screenResults["volume"].astype(str)
|
828
|
+
saveResults["volume"] = saveResults["volume"].astype(str)
|
829
|
+
screenResults.loc[:, "volume"] = screenResults.loc[:, "volume"].apply(
|
830
830
|
lambda x: Utility.tools.formatRatio(float(ImageUtility.PKImageTools.removeAllColorStyles(x)), volumeRatio) if len(str(x).strip()) > 0 else ''
|
831
831
|
)
|
832
|
-
saveResults.loc[:, "
|
832
|
+
saveResults.loc[:, "volume"] = saveResults.loc[:, "volume"].apply(
|
833
833
|
lambda x: str(x) + "x"
|
834
834
|
)
|
835
835
|
screenResults.rename(
|
@@ -1823,7 +1823,7 @@ def main(userArgs=None,optionalFinalOutcome_df=None):
|
|
1823
1823
|
prediction, pText, sText = screener.getNiftyPrediction(
|
1824
1824
|
df=fetcher.fetchLatestNiftyDaily(proxyServer=fetcher.proxyServer)
|
1825
1825
|
)
|
1826
|
-
warningText = "\nNifty AI prediction works best if you request after market is closed. It may not be accurate while market is still open!" if "
|
1826
|
+
warningText = "\nNifty AI prediction works best if you request after market is closed. It may not be accurate while market is still open!" if "open" in Utility.marketStatus() else ""
|
1827
1827
|
try:
|
1828
1828
|
todayHoliday, todayOccassion = PKDateUtilities.isHoliday(PKDateUtilities.currentDateTime())
|
1829
1829
|
nextWeekday = PKDateUtilities.nextWeekday()
|
@@ -1916,10 +1916,12 @@ def main(userArgs=None,optionalFinalOutcome_df=None):
|
|
1916
1916
|
pass
|
1917
1917
|
loadCount = len(stockDictPrimary) if stockDictPrimary is not None else 0
|
1918
1918
|
# Let's use screening only for the stocks for which we could get the data.
|
1919
|
-
savedOrDownloadedKeys = list(stockDictPrimary.keys())
|
1920
|
-
missingStocks = set(listStockCodes) - set(savedOrDownloadedKeys)
|
1921
|
-
|
1922
|
-
|
1919
|
+
savedOrDownloadedKeys = listStockCodes if (userArgs.options is not None and "," in userArgs.options) else list(stockDictPrimary.keys())
|
1920
|
+
missingStocks = set(listStockCodes) - set([ x.replace("-BE","").replace("-BZ","") for x in savedOrDownloadedKeys ])
|
1921
|
+
# print(missingStocks)
|
1922
|
+
# default_logger().debug(missingStocks)
|
1923
|
+
OutputControls().printOutput(f"{colorText.GREEN} [+] Adding {len(savedOrDownloadedKeys)-len(missingStocks)} stocks out of {len(savedOrDownloadedKeys)} to the queue...{colorText.END}")
|
1924
|
+
listStockCodes = list(set(savedOrDownloadedKeys)-set(missingStocks)) if not downloadOnly else savedOrDownloadedKeys
|
1923
1925
|
if downloadOnly:
|
1924
1926
|
OutputControls().printOutput(
|
1925
1927
|
colorText.WARN
|
@@ -2336,7 +2338,7 @@ def analysisFinalResults(screenResults,saveResults,optionalFinalOutcome_df,runOp
|
|
2336
2338
|
analysis_df = screenResults.copy()
|
2337
2339
|
else:
|
2338
2340
|
analysis_df = pd.DataFrame()
|
2339
|
-
index_columns = ["Stock","%Chng","
|
2341
|
+
index_columns = ["Stock","%Chng","volume","Pattern","MA-Signal","Trend(22Prds)","Trend","LTP","LTP@Alert","AlertTime","SqrOff","SqrOffLTP","SqrOffDiff","EoDDiff","DayHighTime","DayHigh","DayHighDiff"]
|
2340
2342
|
final_index_columns = []
|
2341
2343
|
firstScanKey = userPassedArgs.options.split(">|")[0]
|
2342
2344
|
for column in index_columns:
|
@@ -2474,7 +2476,7 @@ def FinishBacktestDataCleanup(backtest_df, df_xray):
|
|
2474
2476
|
"22": "22-Pd",
|
2475
2477
|
"30": "30-Pd",
|
2476
2478
|
"T": "Trend",
|
2477
|
-
"V": "
|
2479
|
+
"V": "volume",
|
2478
2480
|
"M": "MA-Signal",
|
2479
2481
|
}
|
2480
2482
|
if configManager.enablePortfolioCalculations:
|
@@ -3259,17 +3261,17 @@ def printNotifySaveScreenedResults(
|
|
3259
3261
|
with pd.option_context('mode.chained_assignment', None):
|
3260
3262
|
caption_df.rename(columns={"DayHighDiff": "Hgh","EoDDiff":"EoD"}, inplace=True)
|
3261
3263
|
else:
|
3262
|
-
caption_df = saveResultsTrimmed[['LTP','%Chng',
|
3264
|
+
caption_df = saveResultsTrimmed[['LTP','%Chng',"volume"]].head(configManager.telegramSampleNumberRows)
|
3263
3265
|
caption_df.loc[:, "LTP"] = caption_df.loc[:, "LTP"].apply(
|
3264
3266
|
lambda x: str(int(round(float(x),0)))
|
3265
3267
|
)
|
3266
3268
|
caption_df.loc[:, "%Chng"] = caption_df.loc[:, "%Chng"].apply(
|
3267
3269
|
lambda x: f'{int(round(float(x.split(" ")[0].replace("%","")),0))}%'
|
3268
3270
|
)
|
3269
|
-
caption_df.loc[:, "
|
3271
|
+
caption_df.loc[:, "volume"] = caption_df.loc[:, "volume"].apply(
|
3270
3272
|
lambda x: f'{int(round(float(x.replace("x","")),0))}x' if (len(x.replace("x","").strip()) > 0 and not pd.isna(float(x.replace("x","")))) else ''
|
3271
3273
|
)
|
3272
|
-
caption_df.rename(columns={"%Chng": "Ch%","
|
3274
|
+
caption_df.rename(columns={"%Chng": "Ch%","volume":"Vol"}, inplace=True)
|
3273
3275
|
except: # pragma: no cover
|
3274
3276
|
cols = [list(saveResultsTrimmed.columns)[0]]
|
3275
3277
|
cols.extend(list(saveResultsTrimmed.columns[5:]))
|
@@ -3285,7 +3287,7 @@ def printNotifySaveScreenedResults(
|
|
3285
3287
|
).encode("utf-8").decode(STD_ENCODING).replace("-K-----S-----C-----R","-K-----S----C---R").replace("% ","% ").replace("=K=====S=====C=====R","=K=====S====C===R").replace("Vol |","Vol|").replace("Hgh |","Hgh|").replace("EoD |","EoD|").replace("x ","x")
|
3286
3288
|
caption_results = ImageUtility.PKImageTools.removeAllColorStyles(caption_results.replace("-E-----N-----E-----R","-E-----N----E---R").replace("=E=====N=====E=====R","=E=====N====E===R"))
|
3287
3289
|
suggestion_text = "Try @nse_pkscreener_bot for more scans! <i><b><u>You agree that you have read</u></b>:https://pkjmesra.github.io/PKScreener/Disclaimer.txt</i> <b>and accept TOS</b>: https://pkjmesra.github.io/PKScreener/tos.txt <b>STOP using and exit from channel/group, if you do not</b>"
|
3288
|
-
finalCaption = f"{caption}.Feel free to share on social media.
|
3290
|
+
finalCaption = f"{caption}.Feel free to share on social media.open attached image for more. Samples:<pre>{caption_results}</pre>{elapsed_text} {suggestion_text}"
|
3289
3291
|
if not testing:
|
3290
3292
|
if PKDateUtilities.isTradingTime() and not PKDateUtilities.isTodayHoliday()[0]:
|
3291
3293
|
kite_file_path, kite_caption = sendKiteBasketOrderReviewDetails(saveResultsTrimmed,runOptionName,caption,user)
|
@@ -3705,11 +3707,11 @@ def runScanners(
|
|
3705
3707
|
if result is not None:
|
3706
3708
|
if not userPassedArgs.monitor and len(lstscreen) > 0 and userPassedArgs is not None and userPassedArgs.options.split(":")[2] in ["29"]:
|
3707
3709
|
scr_df = pd.DataFrame(lstscreen)
|
3708
|
-
existingColumns = ["Stock","%Chng","LTP","
|
3710
|
+
existingColumns = ["Stock","%Chng","LTP","volume"]
|
3709
3711
|
newColumns = ["BidQty","AskQty","LwrCP","UprCP","VWAP","DayVola","Del(%)"]
|
3710
3712
|
existingColumns.extend(newColumns)
|
3711
3713
|
scr_df = scr_df[existingColumns]
|
3712
|
-
scr_df.sort_values(by=["
|
3714
|
+
scr_df.sort_values(by=["volume","BidQty"], ascending=False, inplace=True)
|
3713
3715
|
tabulated_results = colorText.miniTabulator().tb.tabulate(
|
3714
3716
|
scr_df,
|
3715
3717
|
headers="keys",
|
@@ -142,6 +142,7 @@ m3 = menus()
|
|
142
142
|
m4 = menus()
|
143
143
|
int_timer = None
|
144
144
|
_updater = None
|
145
|
+
QR_CODE_PAYMENT_LINK="upi://pay?pa=PKSCREENER@APL&pn=PKSCREENER&tn=undefined&am=undefined"
|
145
146
|
|
146
147
|
TOP_LEVEL_SCANNER_MENUS = ["X", "B", "MI","DV", "P"] #
|
147
148
|
TOP_LEVEL_SCANNER_SKIP_MENUS = ["M", "S", "F", "G", "C", "T", "D", "I", "E", "U", "L", "Z", "P"] # Last item will be skipped.
|
@@ -426,6 +426,7 @@ def setupLogger(shouldLog=False, trace=False):
|
|
426
426
|
OutputControls().printOutput(colorText.GREEN + f" [+] {log_file_path}"+colorText.END)
|
427
427
|
OutputControls().printOutput(colorText.FAIL + " [+] If you need to share, open this folder, copy and zip the log file to share.\n" + colorText.END)
|
428
428
|
# logger = multiprocessing.log_to_stderr(log.logging.DEBUG)
|
429
|
+
os.environ["PKDevTools_Default_Log_Level"] = str(log.logging.DEBUG)
|
429
430
|
log.setup_custom_logger(
|
430
431
|
"pkscreener",
|
431
432
|
log.logging.DEBUG,
|
@@ -433,31 +434,30 @@ def setupLogger(shouldLog=False, trace=False):
|
|
433
434
|
log_file_path=log_file_path,
|
434
435
|
filter=None,
|
435
436
|
)
|
436
|
-
os.environ["PKDevTools_Default_Log_Level"] = str(log.logging.DEBUG)
|
437
437
|
|
438
438
|
def warnAboutDependencies():
|
439
439
|
if not Imports["talib"]:
|
440
440
|
OutputControls().printOutput(
|
441
441
|
colorText.FAIL
|
442
|
-
+ " [+] TA-Lib is not installed. Looking for
|
442
|
+
+ " [+] TA-Lib is not installed. Looking for pandas_ta_classic."
|
443
443
|
+ colorText.END
|
444
444
|
)
|
445
445
|
sleep(1)
|
446
446
|
issueLink = "https://github.com/pkjmesra/PKScreener"
|
447
447
|
issueLink = f"\x1b[97m\x1b]8;;{issueLink}\x1b\\{issueLink}\x1b]8;;\x1b\\\x1b[0m"
|
448
|
-
if Imports["
|
448
|
+
if Imports["pandas_ta_classic"]:
|
449
449
|
taLink = "https://github.com/ta-lib/ta-lib-python"
|
450
450
|
taLink = f"\x1b[97m\x1b]8;;{taLink}\x1b\\{taLink}\x1b]8;;\x1b\\\x1b[0m"
|
451
451
|
OutputControls().printOutput(
|
452
452
|
colorText.GREEN
|
453
|
-
+ f" [+] Found and falling back on
|
453
|
+
+ f" [+] Found and falling back on pandas_ta_classic.\n [+] For full coverage(candle patterns), you may wish to read the README file in PKScreener repo : {issueLink}\n [+] or follow instructions from\n [+] {taLink}"
|
454
454
|
+ colorText.END
|
455
455
|
)
|
456
456
|
sleep(1)
|
457
457
|
else:
|
458
458
|
OutputControls().printOutput(
|
459
459
|
colorText.FAIL
|
460
|
-
+ f" [+] Neither ta-lib nor
|
460
|
+
+ f" [+] Neither ta-lib nor pandas_ta_classic was located. You need at least one of them to continue! \n [+] Please follow instructions from README file under PKScreener repo: {issueLink}"
|
461
461
|
+ colorText.END
|
462
462
|
)
|
463
463
|
OutputControls().takeUserInput("Press any key to try anyway...")
|
@@ -933,10 +933,10 @@ def pkscreenercli():
|
|
933
933
|
OutputControls().printOutput(e)
|
934
934
|
traceback.print_exc()
|
935
935
|
pass
|
936
|
-
finally:
|
937
|
-
|
938
|
-
|
939
|
-
|
936
|
+
# finally:
|
937
|
+
# from PKDevTools.classes.PKBackupRestore import restore_backup
|
938
|
+
# restore_backup()
|
939
|
+
# sleep(3)
|
940
940
|
# import threading
|
941
941
|
# from pkscreener.globals import tryLoadDataOnBackgroundThread
|
942
942
|
# ping_thread = threading.Thread(target=tryLoadDataOnBackgroundThread, daemon=True)
|
@@ -13,13 +13,13 @@ lxml==4.9.4 # 5.0.0 or above causes problems.
|
|
13
13
|
numpy #>=1.26.4
|
14
14
|
openpyxl #>=3.1.5
|
15
15
|
pandas #>=2.2.3
|
16
|
-
|
16
|
+
pandas-ta-classic #>=0.4.67b0
|
17
17
|
# This is required because https://github.com/erocarrera/pefile/issues/420
|
18
18
|
# and https://github.com/pyinstaller/pyinstaller/issues/8762
|
19
19
|
# and https://github.com/pyinstaller/pyinstaller/issues/7269
|
20
20
|
pefile>=2023.2.7,<2024.8.26
|
21
21
|
Pillow #>=9.5.0,<=9.5.0 # Keep at this version because getsize_multiline is deprecated/removed in higher versions
|
22
|
-
PKDevTools>=0.13.
|
22
|
+
PKDevTools>=0.13.20250908.302
|
23
23
|
PKNSETools>=0.1.20250122.139
|
24
24
|
Pyarrow #>=17.0.0
|
25
25
|
pyppeteer #>=2.0.0
|
@@ -39,7 +39,7 @@ tensorflow==2.16.1 # https://github.com/tensorflow/tensorflow/issues/62075
|
|
39
39
|
urllib3 #>=1.26.20
|
40
40
|
vectorbt #>=0.26.2
|
41
41
|
xlsxwriter #>=3.2.0
|
42
|
-
yfinance==0.2.54 #>=0.2.44 #==0.1.87
|
42
|
+
# yfinance==0.2.54 #>=0.2.44 #==0.1.87
|
43
43
|
# windows-curses; "windows" in sys.platform
|
44
44
|
# https://github.com/pkjmesra/PKScreener/blob/main/.github/dependencies/TA_Lib-0.4.28-cp311-cp311-win_amd64.whl; "windows" in sys.platform
|
45
45
|
|
@@ -1,9 +1,9 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: pkscreener
|
3
|
-
Version: 0.46.
|
3
|
+
Version: 0.46.20250908.764
|
4
4
|
Summary: A Python-based stock screener for NSE, India with alerts to Telegram Channel (pkscreener)
|
5
5
|
Home-page: https://github.com/pkjmesra/pkscreener
|
6
|
-
Download-URL: https://github.com/pkjmesra/pkscreener/archive/v0.46.
|
6
|
+
Download-URL: https://github.com/pkjmesra/pkscreener/archive/v0.46.20250908.764.zip
|
7
7
|
Author: pkjmesra
|
8
8
|
Author-email: pkjmesra@gmail.com
|
9
9
|
License: OSI Approved (MIT)
|
@@ -30,10 +30,10 @@ Requires-Dist: lxml==4.9.4
|
|
30
30
|
Requires-Dist: numpy
|
31
31
|
Requires-Dist: openpyxl
|
32
32
|
Requires-Dist: pandas
|
33
|
-
Requires-Dist:
|
33
|
+
Requires-Dist: pandas-ta-classic
|
34
34
|
Requires-Dist: pefile<2024.8.26,>=2023.2.7
|
35
35
|
Requires-Dist: Pillow
|
36
|
-
Requires-Dist: PKDevTools>=0.13.
|
36
|
+
Requires-Dist: PKDevTools>=0.13.20250908.302
|
37
37
|
Requires-Dist: PKNSETools>=0.1.20250122.139
|
38
38
|
Requires-Dist: Pyarrow
|
39
39
|
Requires-Dist: pyppeteer
|
@@ -50,7 +50,6 @@ Requires-Dist: tensorflow==2.16.1
|
|
50
50
|
Requires-Dist: urllib3
|
51
51
|
Requires-Dist: vectorbt
|
52
52
|
Requires-Dist: xlsxwriter
|
53
|
-
Requires-Dist: yfinance==0.2.54
|
54
53
|
Requires-Dist: advanced_ta
|
55
54
|
Dynamic: author
|
56
55
|
Dynamic: author-email
|
@@ -245,7 +244,7 @@ The story is similar for other low severity vulnerabilities that docker might sh
|
|
245
244
|
# Installing the latest version from PyPi.
|
246
245
|
* Go ahead and install using `pip install pkscreener`. The releases page also has the latest wheels for multiple platforms.
|
247
246
|
* This should install all of the major dependencies, except maybe, TA-Lib.
|
248
|
-
* This app can still run without TA-Lib, but if you need to install TA-Lib for technical indicators (which otherwise is used from `
|
247
|
+
* This app can still run without TA-Lib, but if you need to install TA-Lib for technical indicators (which otherwise is used from `pandas_ta_classic` in the absence of TA-Lib), you can do this: Head to `.github/dependencies/` under this repo. Download the respective TA-Lib file/whl file and install either from the .whl file or from source. Check out any of the workflow files for steps to install TA-Lib.
|
249
248
|
|
250
249
|
For example:
|
251
250
|
|
@@ -398,15 +397,15 @@ If you are a 3rd year or final year engineering graduate or pursuing masters in
|
|
398
397
|
[MADE-IN-INDIA-badge]: https://img.shields.io/badge/MADE%20WITH%20%E2%9D%A4%20IN-INDIA-orange
|
399
398
|
[MADE-IN-INDIA]: https://en.wikipedia.org/wiki/India
|
400
399
|
[Windows-badge]: https://img.shields.io/badge/Windows-0078D6?logo=windows&logoColor=white
|
401
|
-
[Windows]: https://github.com/pkjmesra/PKScreener/releases/download/0.46.
|
400
|
+
[Windows]: https://github.com/pkjmesra/PKScreener/releases/download/0.46.20250810.756/pkscreenercli.exe
|
402
401
|
[Linux-badge_x64]: https://img.shields.io/badge/Linux(x64)-FCC624?logo=linux&logoColor=black
|
403
|
-
[Linux_x64]: https://github.com/pkjmesra/PKScreener/releases/download/0.46.
|
402
|
+
[Linux_x64]: https://github.com/pkjmesra/PKScreener/releases/download/0.46.20250810.756/pkscreenercli_x64.bin
|
404
403
|
[Linux-badge_arm64]: https://img.shields.io/badge/Linux(arm64)-FCC624?logo=linux&logoColor=black
|
405
|
-
[Linux_arm64]: https://github.com/pkjmesra/PKScreener/releases/download/0.46.
|
404
|
+
[Linux_arm64]: https://github.com/pkjmesra/PKScreener/releases/download/0.46.20250810.756/pkscreenercli_arm64.bin
|
406
405
|
[Mac OS-badge_x64]: https://img.shields.io/badge/mac%20os(x64)-D3D3D3?logo=apple&logoColor=000000
|
407
|
-
[Mac OS_x64]: https://github.com/pkjmesra/PKScreener/releases/download/0.46.
|
406
|
+
[Mac OS_x64]: https://github.com/pkjmesra/PKScreener/releases/download/0.46.20250810.756/pkscreenercli_x64.run
|
408
407
|
[Mac OS-badge_arm64]: https://img.shields.io/badge/mac%20os(arm64)-D3D3D3?logo=apple&logoColor=000000
|
409
|
-
[Mac OS_arm64]: https://github.com/pkjmesra/PKScreener/releases/download/0.46.
|
408
|
+
[Mac OS_arm64]: https://github.com/pkjmesra/PKScreener/releases/download/0.46.20250810.756/pkscreenercli_arm64.run
|
410
409
|
[GitHub release (latest by date)-badge]: https://img.shields.io/github/v/release/pkjmesra/PKScreener
|
411
410
|
[GitHub release (latest by date)]: https://github.com/pkjmesra/PKScreener/releases/latest
|
412
411
|
[pypi-badge]: https://img.shields.io/pypi/v/pkscreener.svg?style=flat-square
|
@@ -0,0 +1,58 @@
|
|
1
|
+
pkscreener-0.46.20250908.764.data/purelib/pkscreener/Disclaimer.txt,sha256=kBZQSQCFfL2kc1bijXWndZzkjMTtnpH_B7XtDPPMcuw,1396
|
2
|
+
pkscreener-0.46.20250908.764.data/purelib/pkscreener/LICENSE-Others.txt,sha256=GvIyMMu6lIBXiJP_9wgmqMWotJAgqoYJbGNjprIwRTg,271838
|
3
|
+
pkscreener-0.46.20250908.764.data/purelib/pkscreener/LICENSE.txt,sha256=CdnyGrl-xRYX67ZkdERZWHr6BlTxOyg8Z8sK1XQ5Xsg,1078
|
4
|
+
pkscreener-0.46.20250908.764.data/purelib/pkscreener/LogoWM.txt,sha256=7Njnavpy_FKY4Iwbzv1JqsYMcOdkDSKAKXP3SAItKV0,14868
|
5
|
+
pkscreener-0.46.20250908.764.data/purelib/pkscreener/README.txt,sha256=Jv6r_UyWzEVtpv0xAwt0Z43qlEmd8E3wuVLhk33jzBQ,33153
|
6
|
+
pkscreener-0.46.20250908.764.data/purelib/pkscreener/__init__.py,sha256=n6lLvxcQaR3LyqttsXiUEwtlpL3MmQjuZS3zhvyG3Xc,1651
|
7
|
+
pkscreener-0.46.20250908.764.data/purelib/pkscreener/courbd.ttf,sha256=SKpnp-BRs7AZcdI83nencS3Q7xe0anbbP1YMOxLlEhU,791436
|
8
|
+
pkscreener-0.46.20250908.764.data/purelib/pkscreener/globals.py,sha256=Qf-pUQ5ylzMoWRpQBP1CpRml_-rwoyyEn0kqDebcMOo,246321
|
9
|
+
pkscreener-0.46.20250908.764.data/purelib/pkscreener/pkscreener.ini,sha256=QKs6j4qhyH37L_MdG3ztAIwgqs4c3qihuqDIoex-V2g,2391
|
10
|
+
pkscreener-0.46.20250908.764.data/purelib/pkscreener/pkscreenerbot.py,sha256=rDwe92q42lSYltE_2KBjF2wSMFhj9SXiEty-npx3D_E,118037
|
11
|
+
pkscreener-0.46.20250908.764.data/purelib/pkscreener/pkscreenercli.py,sha256=BSzG5Yr3JfPQpxlT9qMNJplLTbBYcadW0O9UE7O9EBI,58801
|
12
|
+
pkscreener-0.46.20250908.764.data/purelib/pkscreener/requirements.txt,sha256=7Q3U8pDNfLtnNamrawD8mVD811E5OoVVk5ENHxnHNGg,1503
|
13
|
+
pkscreener-0.46.20250908.764.data/purelib/pkscreener/classes/ArtTexts.py,sha256=LZ8ynyS8woliv8bM9Nq4aU0VCoJDJU0FgZk8V5zYPmg,19504
|
14
|
+
pkscreener-0.46.20250908.764.data/purelib/pkscreener/classes/AssetsManager.py,sha256=OcwZPOWRMMhL8gzkEC8TMyanHQBEVweUV7S49s0AJaY,32133
|
15
|
+
pkscreener-0.46.20250908.764.data/purelib/pkscreener/classes/Backtest.py,sha256=BaNHaaraXD0SG7WfJVc2kj5XuFEroQX8nm-GhZt5g8E,10530
|
16
|
+
pkscreener-0.46.20250908.764.data/purelib/pkscreener/classes/Barometer.py,sha256=WPrgtIXb1nIbb-FnuRs-yvOQ5baNQRBgUR_zWg1moxk,9464
|
17
|
+
pkscreener-0.46.20250908.764.data/purelib/pkscreener/classes/BaseScreeningStatistics.py,sha256=u5t1wf-HsZ8xEtprON55ehIR3F2LNNq8LvwgIrhYRmU,3000
|
18
|
+
pkscreener-0.46.20250908.764.data/purelib/pkscreener/classes/CandlePatterns.py,sha256=8wo6rTXJ1C3im27yzNRgTTKk8FvZpJFzDC6fesfrkCE,17074
|
19
|
+
pkscreener-0.46.20250908.764.data/purelib/pkscreener/classes/Changelog.py,sha256=vUOpca28OACNhavAmjBm4xco3u6fcHqWlnlmCJqO5Lk,1469
|
20
|
+
pkscreener-0.46.20250908.764.data/purelib/pkscreener/classes/ConfigManager.py,sha256=sfm_5maWIL5-pfOYcQp-hd11CAo-L3e5UX8I0aPn6PA,54406
|
21
|
+
pkscreener-0.46.20250908.764.data/purelib/pkscreener/classes/ConsoleMenuUtility.py,sha256=fyR7dEsAaEWEe5SyaVgwLPdU4h4pI8SozUhsPZXShpg,10037
|
22
|
+
pkscreener-0.46.20250908.764.data/purelib/pkscreener/classes/ConsoleUtility.py,sha256=WgPLO2gYJhnTLXm6yu1z9pLJcGy_fNCGBkwewrrunUo,12181
|
23
|
+
pkscreener-0.46.20250908.764.data/purelib/pkscreener/classes/Fetcher.py,sha256=2qlLvCfMAIsl1b-j6Mr0qRKq5d5vhqh8bRCJwws7fNE,16591
|
24
|
+
pkscreener-0.46.20250908.764.data/purelib/pkscreener/classes/GlobalStore.py,sha256=IzoYMybXpVVf6YwZi7j34rP-hNd7sMened8TAMu_-A8,3709
|
25
|
+
pkscreener-0.46.20250908.764.data/purelib/pkscreener/classes/ImageUtility.py,sha256=h1h9fiJJV6Mkdo0kfrEEbQPwgXH0j4fsczVh_Uky5mA,37032
|
26
|
+
pkscreener-0.46.20250908.764.data/purelib/pkscreener/classes/MarketMonitor.py,sha256=p12ZYGhfK__ddIwbu1_VZ1CSptba8ZHZj5dcx5IL9Tk,22141
|
27
|
+
pkscreener-0.46.20250908.764.data/purelib/pkscreener/classes/MarketStatus.py,sha256=ZhNi3LUyIOtOwWIoidI0bxidDlYJAKymMyQb7oDPClA,3786
|
28
|
+
pkscreener-0.46.20250908.764.data/purelib/pkscreener/classes/MenuOptions.py,sha256=abK_ZsKg8pND_5ZVdLsY4sjaVerButVsWsHSdWdjPGM,64558
|
29
|
+
pkscreener-0.46.20250908.764.data/purelib/pkscreener/classes/Messenger.py,sha256=peyY-YiqdC1bp-3DlJXILRa9HGYbqGVzf1wil0fYv98,8396
|
30
|
+
pkscreener-0.46.20250908.764.data/purelib/pkscreener/classes/OtaUpdater.py,sha256=_7-nFAC-vAcmZ1Nwi5g5tfp7hKQQPuLUnBCOzrwC39g,13491
|
31
|
+
pkscreener-0.46.20250908.764.data/purelib/pkscreener/classes/PKAnalytics.py,sha256=qLXibEx18kMjZno7EVhyZBblnXWWo1bC2Kjrd8OskgE,7526
|
32
|
+
pkscreener-0.46.20250908.764.data/purelib/pkscreener/classes/PKDataService.py,sha256=BipM8Z4rS6h12cF6VWv_u4Z8ee7psMFd1yUojejW1Ag,3393
|
33
|
+
pkscreener-0.46.20250908.764.data/purelib/pkscreener/classes/PKDemoHandler.py,sha256=r4KrZF8TaOu1J0nu8sUsgWEvnbndboWQQvz69GOy1Fk,2207
|
34
|
+
pkscreener-0.46.20250908.764.data/purelib/pkscreener/classes/PKMarketOpenCloseAnalyser.py,sha256=YgSKGzdMkVGtapK_7A0AUPZZ7L9cLV3Yz-X7TgZpu1U,34157
|
35
|
+
pkscreener-0.46.20250908.764.data/purelib/pkscreener/classes/PKPremiumHandler.py,sha256=r16-u9fyc0ftgnSnZnz-JusTfEzyQIyKkvgbPuSd7W4,5611
|
36
|
+
pkscreener-0.46.20250908.764.data/purelib/pkscreener/classes/PKScanRunner.py,sha256=QHZq5flm4N5_uzVxjiuJqnB_5PL89MEpXAcxVCIZhNg,26795
|
37
|
+
pkscreener-0.46.20250908.764.data/purelib/pkscreener/classes/PKScheduledTaskProgress.py,sha256=h19ZuxoalB50pnZjntFh12b9mBozvMqhKYq6TL18vo4,1657
|
38
|
+
pkscreener-0.46.20250908.764.data/purelib/pkscreener/classes/PKScheduler.py,sha256=qThoz0yXLmHEWAiD_TdkIrzJb37b_m830JJFrkN1Tio,8814
|
39
|
+
pkscreener-0.46.20250908.764.data/purelib/pkscreener/classes/PKSpreadsheets.py,sha256=1I7YGGPPY879K5JeTZ_d1FNCpjloh6TZrx91JlwT20o,8298
|
40
|
+
pkscreener-0.46.20250908.764.data/purelib/pkscreener/classes/PKTask.py,sha256=4q87uD2cXvp0AbP6I73xPP39F0mfnpHQutsxxqpnxJM,1867
|
41
|
+
pkscreener-0.46.20250908.764.data/purelib/pkscreener/classes/PKUserRegistration.py,sha256=SIEpkMscmUav7dXDcRUDZmlb5LeRo6b-Tx-h15ED_88,11589
|
42
|
+
pkscreener-0.46.20250908.764.data/purelib/pkscreener/classes/Pktalib.py,sha256=PkNDMbRZc4kf5f0SZg_mn6TWo4iIjVXqmr9SWFE4aEs,33474
|
43
|
+
pkscreener-0.46.20250908.764.data/purelib/pkscreener/classes/Portfolio.py,sha256=JZ93n3Zk9nkSFaX-lHyQiFnavHVmHPFoy-L_4gugj54,13895
|
44
|
+
pkscreener-0.46.20250908.764.data/purelib/pkscreener/classes/PortfolioXRay.py,sha256=tk7gGheJRxYLA54qCRZSs0uBgGZFN0Oh5NPSXYcf7Z4,48339
|
45
|
+
pkscreener-0.46.20250908.764.data/purelib/pkscreener/classes/ScreeningStatistics.py,sha256=xzqBdYuTtni9-jOp8rS-MV1rVGdpw67ygX_gUzsmu88,221864
|
46
|
+
pkscreener-0.46.20250908.764.data/purelib/pkscreener/classes/StockScreener.py,sha256=4LgU-LbTfkwUDhi9yRAT2imN3CXt3JVdwXXzkKG2QII,68004
|
47
|
+
pkscreener-0.46.20250908.764.data/purelib/pkscreener/classes/StockSentiment.py,sha256=WL7TBAHDSIN5cgZ9uTbbEFnUPo4G-YIzEv16RpPGaro,3546
|
48
|
+
pkscreener-0.46.20250908.764.data/purelib/pkscreener/classes/UserMenuChoicesHandler.py,sha256=_fTCscTLEjoU-n12V9237uDN6Jf8nGCvGdBVkpD3Ap4,4947
|
49
|
+
pkscreener-0.46.20250908.764.data/purelib/pkscreener/classes/Utility.py,sha256=FAioF11ssWAl3yzhsXZQBmykj5No8U6ii9DZEaazUHQ,13886
|
50
|
+
pkscreener-0.46.20250908.764.data/purelib/pkscreener/classes/WorkflowManager.py,sha256=YRUiZSq83SEx2qB0wTBDE4KFaYqEz1Qu4FSCAzl6xzU,5663
|
51
|
+
pkscreener-0.46.20250908.764.data/purelib/pkscreener/classes/__init__.py,sha256=DLvsitDgYNK7jhT7weGs9Kmmk2-jmZMYsudR-fknRl4,28
|
52
|
+
pkscreener-0.46.20250908.764.data/purelib/pkscreener/classes/keys.py,sha256=LQq_t1lSh0x4TbRCIDhoCil3xctgLLeVk5f2vgrl1tk,6789
|
53
|
+
pkscreener-0.46.20250908.764.dist-info/licenses/LICENSE,sha256=CdnyGrl-xRYX67ZkdERZWHr6BlTxOyg8Z8sK1XQ5Xsg,1078
|
54
|
+
pkscreener-0.46.20250908.764.dist-info/METADATA,sha256=EOC8FGhCH82-_Ag4pns6y66ecINRhaUQEiQA4nvR-Wc,35155
|
55
|
+
pkscreener-0.46.20250908.764.dist-info/WHEEL,sha256=6TsICjgOR7isz_jYr-ssV7RSRmh1_0Z7_b5ESlzfzVY,104
|
56
|
+
pkscreener-0.46.20250908.764.dist-info/entry_points.txt,sha256=Pm30xm4sU7YFtFJUC-Te8VlqOvYAvWKFFA5AfQE0xGY,120
|
57
|
+
pkscreener-0.46.20250908.764.dist-info/top_level.txt,sha256=oIfcPPw58Q4KU-GDqp25dXbrtvxYXJBCo_em6i5aVvY,11
|
58
|
+
pkscreener-0.46.20250908.764.dist-info/RECORD,,
|
@@ -1 +0,0 @@
|
|
1
|
-
VERSION='0.46.20250810.756'
|