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.
Files changed (60) hide show
  1. {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/LICENSE-Others.txt +1 -1
  2. {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/README.txt +6 -6
  3. {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/__init__.py +2 -2
  4. {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/AssetsManager.py +13 -29
  5. {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/Backtest.py +5 -5
  6. {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/CandlePatterns.py +23 -23
  7. {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/ConfigManager.py +13 -1
  8. {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/ConsoleUtility.py +1 -1
  9. {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/Fetcher.py +26 -20
  10. {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/ImageUtility.py +1 -1
  11. {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/MarketMonitor.py +6 -6
  12. {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/MarketStatus.py +3 -2
  13. {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/PKMarketOpenCloseAnalyser.py +14 -14
  14. {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/PKScanRunner.py +2 -2
  15. {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/Pktalib.py +36 -36
  16. {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/PortfolioXRay.py +5 -5
  17. {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/ScreeningStatistics.py +457 -445
  18. {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/StockScreener.py +47 -34
  19. {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/Utility.py +4 -3
  20. pkscreener-0.46.20250908.764.data/purelib/pkscreener/classes/__init__.py +1 -0
  21. {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/globals.py +25 -23
  22. {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/pkscreenerbot.py +1 -0
  23. {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/pkscreenercli.py +9 -9
  24. {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/requirements.txt +3 -3
  25. {pkscreener-0.46.20250810.756.dist-info → pkscreener-0.46.20250908.764.dist-info}/METADATA +10 -11
  26. pkscreener-0.46.20250908.764.dist-info/RECORD +58 -0
  27. pkscreener-0.46.20250810.756.data/purelib/pkscreener/classes/__init__.py +0 -1
  28. pkscreener-0.46.20250810.756.dist-info/RECORD +0 -58
  29. {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/Disclaimer.txt +0 -0
  30. {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/LICENSE.txt +0 -0
  31. {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/LogoWM.txt +0 -0
  32. {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/ArtTexts.py +0 -0
  33. {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/Barometer.py +0 -0
  34. {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/BaseScreeningStatistics.py +0 -0
  35. {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/Changelog.py +0 -0
  36. {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/ConsoleMenuUtility.py +0 -0
  37. {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/GlobalStore.py +0 -0
  38. {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/MenuOptions.py +0 -0
  39. {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/Messenger.py +0 -0
  40. {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/OtaUpdater.py +0 -0
  41. {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/PKAnalytics.py +0 -0
  42. {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/PKDataService.py +0 -0
  43. {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/PKDemoHandler.py +0 -0
  44. {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/PKPremiumHandler.py +0 -0
  45. {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/PKScheduledTaskProgress.py +0 -0
  46. {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/PKScheduler.py +0 -0
  47. {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/PKSpreadsheets.py +0 -0
  48. {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/PKTask.py +0 -0
  49. {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/PKUserRegistration.py +0 -0
  50. {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/Portfolio.py +0 -0
  51. {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/StockSentiment.py +0 -0
  52. {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/UserMenuChoicesHandler.py +0 -0
  53. {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/WorkflowManager.py +0 -0
  54. {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/keys.py +0 -0
  55. {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/courbd.ttf +0 -0
  56. {pkscreener-0.46.20250810.756.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/pkscreener.ini +0 -0
  57. {pkscreener-0.46.20250810.756.dist-info → pkscreener-0.46.20250908.764.dist-info}/WHEEL +0 -0
  58. {pkscreener-0.46.20250810.756.dist-info → pkscreener-0.46.20250908.764.dist-info}/entry_points.txt +0 -0
  59. {pkscreener-0.46.20250810.756.dist-info → pkscreener-0.46.20250908.764.dist-info}/licenses/LICENSE +0 -0
  60. {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 pandas_ta.
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
- # if data is None or (data is not None and not data.isnull().values.all(axis=0)[0]):
723
- # hostRef.default_logger.debug(f"StockDataEmptyException:{stock}: {e}", exc_info=True)
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
- # if userArgsLog:
727
- # hostRef.default_logger.debug(f"EligibilityConditionNotMet:{stock}: {e}", exc_info=True)
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
- # if userArgsLog:
731
- # hostRef.default_logger.debug(f"NotNewlyListed:{stock}: {e}", exc_info=True)
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
- # if userArgsLog:
735
- # hostRef.default_logger.debug(f"NotAStageTwoStock:{stock}: {e}", exc_info=True)
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
- # if userArgsLog:
739
- # hostRef.default_logger.debug(f"NotEnoughVolumeAsPerConfig:{stock}: {e}", exc_info=True)
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
- # if userArgsLog:
743
- # hostRef.default_logger.debug(f"DownloadDataOnly:{stock}: {e}", exc_info=True)
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
- # hostRef.default_logger.debug(f"MFIStatus: {stock}:\n{ex}", exc_info=True)
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
- # hostRef.default_logger.debug(f"FairValue: {stock}:\n{ex}", exc_info=True)
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
- # if userArgsLog:
766
- # hostRef.default_logger.debug(f"LTPNotInConfiguredRange:{stock}: {e}", exc_info=True)
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
- # if userArgsLog:
770
- # hostRef.default_logger.debug(f"KeyError:{stock}: {e}", exc_info=True)
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
- # if userArgsLog:
774
- # hostRef.default_logger.debug(f"OSError:{stock}: {e}", exc_info=True)
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
- # if userArgsLog:
778
- # hostRef.default_logger.debug(f"Exception:{stock}: {e}", exc_info=True)
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
- 'Open':'first',
909
- 'High':'max',
910
- 'Low':'min',
911
- 'Close':'last',
920
+ "open":'first',
921
+ "high":'max',
922
+ "low":'min',
923
+ "close":'last',
912
924
  'Adj Close': 'last',
913
- 'Volume':'sum'
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["High"]>0] # resampling can introduce 0 value rows for non-market hours
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
- "Volume",
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
- "Volume": "",
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
- "Volume": "",
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 "Close" in lngStatus and nseStatus == "Open":
89
- lngStatus = lngStatus.replace("Closed","Open")
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="actions-data-download",hideOutput=False,branchName="actions-data-download"):
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[:, "Volume"] = detaildf.loc[:, "Volume"].apply(
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 = ["Volume"] if "RSI" not in menuChoiceHierarchy else ("RSIi" if (isTrading or "RSIi" in saveResults.columns) else "RSI")
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 = ["Volume"]
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 = ["Volume"]
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 ["Volume"]
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 ["Volume"]
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['Volume'] = screenResults['Volume'].astype(str)
828
- saveResults['Volume'] = saveResults['Volume'].astype(str)
829
- screenResults.loc[:, "Volume"] = screenResults.loc[:, "Volume"].apply(
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[:, "Volume"] = saveResults.loc[:, "Volume"].apply(
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 "Open" in Utility.marketStatus() else ""
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
- OutputControls().printOutput(f"{colorText.GREEN} [+] Adding {len(listStockCodes)-len(missingStocks)} stocks out of {len(listStockCodes)} to the queue...{colorText.END}")
1922
- listStockCodes = list(set(listStockCodes)-set(missingStocks)) if not downloadOnly else listStockCodes
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","Volume","Pattern","MA-Signal","Trend(22Prds)","Trend","LTP","LTP@Alert","AlertTime","SqrOff","SqrOffLTP","SqrOffDiff","EoDDiff","DayHighTime","DayHigh","DayHighDiff"]
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": "Volume",
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','Volume']].head(configManager.telegramSampleNumberRows)
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[:, "Volume"] = caption_df.loc[:, "Volume"].apply(
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%","Volume":"Vol"}, inplace=True)
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.Open attached image for more. Samples:<pre>{caption_results}</pre>{elapsed_text} {suggestion_text}"
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","Volume"]
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=["Volume","BidQty"], ascending=False, inplace=True)
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 pandas_ta."
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["pandas_ta"]:
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 pandas_ta.\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}"
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 pandas_ta was located. You need at least one of them to continue! \n [+] Please follow instructions from README file under PKScreener repo: {issueLink}"
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
- from PKDevTools.classes.PKBackupRestore import restore_backup
938
- restore_backup()
939
- sleep(3)
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
- pandas_ta #>=0.3.14b0
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.20250126.268
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.20250810.756
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.20250810.756.zip
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: pandas_ta
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.20250126.268
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 `pandas_ta` 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.
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.20250730.755/pkscreenercli.exe
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.20250730.755/pkscreenercli_x64.bin
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.20250730.755/pkscreenercli_arm64.bin
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.20250730.755/pkscreenercli_x64.run
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.20250730.755/pkscreenercli_arm64.run
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'