pkscreener 0.46.20250728.754__cp310-cp310-macosx_13_0_arm64.whl → 0.46.20250908.764__cp310-cp310-macosx_13_0_arm64.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.20250728.754.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/LICENSE-Others.txt +1 -1
  2. {pkscreener-0.46.20250728.754.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/README.txt +6 -6
  3. {pkscreener-0.46.20250728.754.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/__init__.py +2 -2
  4. {pkscreener-0.46.20250728.754.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/AssetsManager.py +13 -29
  5. {pkscreener-0.46.20250728.754.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/Backtest.py +5 -5
  6. {pkscreener-0.46.20250728.754.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/CandlePatterns.py +23 -23
  7. {pkscreener-0.46.20250728.754.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/ConfigManager.py +14 -2
  8. {pkscreener-0.46.20250728.754.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/ConsoleUtility.py +1 -1
  9. {pkscreener-0.46.20250728.754.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/Fetcher.py +26 -20
  10. {pkscreener-0.46.20250728.754.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/ImageUtility.py +1 -1
  11. {pkscreener-0.46.20250728.754.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/MarketMonitor.py +6 -6
  12. {pkscreener-0.46.20250728.754.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/MarketStatus.py +3 -2
  13. {pkscreener-0.46.20250728.754.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/MenuOptions.py +4 -4
  14. {pkscreener-0.46.20250728.754.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/PKMarketOpenCloseAnalyser.py +14 -14
  15. {pkscreener-0.46.20250728.754.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/PKScanRunner.py +2 -2
  16. {pkscreener-0.46.20250728.754.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/Pktalib.py +36 -36
  17. {pkscreener-0.46.20250728.754.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/PortfolioXRay.py +5 -5
  18. {pkscreener-0.46.20250728.754.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/ScreeningStatistics.py +457 -445
  19. {pkscreener-0.46.20250728.754.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/StockScreener.py +47 -34
  20. {pkscreener-0.46.20250728.754.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/Utility.py +4 -3
  21. pkscreener-0.46.20250908.764.data/purelib/pkscreener/classes/__init__.py +1 -0
  22. {pkscreener-0.46.20250728.754.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/globals.py +26 -24
  23. {pkscreener-0.46.20250728.754.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/pkscreenerbot.py +1 -0
  24. {pkscreener-0.46.20250728.754.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/pkscreenercli.py +9 -9
  25. {pkscreener-0.46.20250728.754.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/requirements.txt +3 -3
  26. {pkscreener-0.46.20250728.754.dist-info → pkscreener-0.46.20250908.764.dist-info}/METADATA +10 -11
  27. pkscreener-0.46.20250908.764.dist-info/RECORD +58 -0
  28. pkscreener-0.46.20250728.754.data/purelib/pkscreener/classes/__init__.py +0 -1
  29. pkscreener-0.46.20250728.754.dist-info/RECORD +0 -58
  30. {pkscreener-0.46.20250728.754.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/Disclaimer.txt +0 -0
  31. {pkscreener-0.46.20250728.754.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/LICENSE.txt +0 -0
  32. {pkscreener-0.46.20250728.754.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/LogoWM.txt +0 -0
  33. {pkscreener-0.46.20250728.754.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/ArtTexts.py +0 -0
  34. {pkscreener-0.46.20250728.754.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/Barometer.py +0 -0
  35. {pkscreener-0.46.20250728.754.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/BaseScreeningStatistics.py +0 -0
  36. {pkscreener-0.46.20250728.754.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/Changelog.py +0 -0
  37. {pkscreener-0.46.20250728.754.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/ConsoleMenuUtility.py +0 -0
  38. {pkscreener-0.46.20250728.754.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/GlobalStore.py +0 -0
  39. {pkscreener-0.46.20250728.754.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/Messenger.py +0 -0
  40. {pkscreener-0.46.20250728.754.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/OtaUpdater.py +0 -0
  41. {pkscreener-0.46.20250728.754.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/PKAnalytics.py +0 -0
  42. {pkscreener-0.46.20250728.754.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/PKDataService.py +0 -0
  43. {pkscreener-0.46.20250728.754.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/PKDemoHandler.py +0 -0
  44. {pkscreener-0.46.20250728.754.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/PKPremiumHandler.py +0 -0
  45. {pkscreener-0.46.20250728.754.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/PKScheduledTaskProgress.py +0 -0
  46. {pkscreener-0.46.20250728.754.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/PKScheduler.py +0 -0
  47. {pkscreener-0.46.20250728.754.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/PKSpreadsheets.py +0 -0
  48. {pkscreener-0.46.20250728.754.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/PKTask.py +0 -0
  49. {pkscreener-0.46.20250728.754.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/PKUserRegistration.py +0 -0
  50. {pkscreener-0.46.20250728.754.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/Portfolio.py +0 -0
  51. {pkscreener-0.46.20250728.754.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/StockSentiment.py +0 -0
  52. {pkscreener-0.46.20250728.754.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/UserMenuChoicesHandler.py +0 -0
  53. {pkscreener-0.46.20250728.754.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/WorkflowManager.py +0 -0
  54. {pkscreener-0.46.20250728.754.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/classes/keys.py +0 -0
  55. {pkscreener-0.46.20250728.754.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/courbd.ttf +0 -0
  56. {pkscreener-0.46.20250728.754.data → pkscreener-0.46.20250908.764.data}/purelib/pkscreener/pkscreener.ini +0 -0
  57. {pkscreener-0.46.20250728.754.dist-info → pkscreener-0.46.20250908.764.dist-info}/LICENSE +0 -0
  58. {pkscreener-0.46.20250728.754.dist-info → pkscreener-0.46.20250908.764.dist-info}/WHEEL +0 -0
  59. {pkscreener-0.46.20250728.754.dist-info → pkscreener-0.46.20250908.764.dist-info}/entry_points.txt +0 -0
  60. {pkscreener-0.46.20250728.754.dist-info → pkscreener-0.46.20250908.764.dist-info}/top_level.txt +0 -0
@@ -38,7 +38,7 @@ import pkscreener.classes.Utility as Utility
38
38
  from pkscreener import Imports
39
39
  from pkscreener.classes.Pktalib import pktalib
40
40
  from PKDevTools.classes.OutputControls import OutputControls
41
- from PKDevTools.classes import Archiver
41
+ from PKDevTools.classes import Archiver, log
42
42
  from PKNSETools.morningstartools import Stock
43
43
 
44
44
  if sys.version_info >= (3, 11):
@@ -90,13 +90,25 @@ class ScreeningStatistics:
90
90
  self.configManager = configManager
91
91
  self.default_logger = default_logger
92
92
  self.shouldLog = shouldLog
93
+ self.setupLogger(self.default_logger.level)
94
+
95
+ def setupLogger(self, log_level):
96
+ if log_level > 0:
97
+ os.environ["PKDevTools_Default_Log_Level"] = str(log_level)
98
+ log.setup_custom_logger(
99
+ "pkscreener",
100
+ log_level,
101
+ trace=False,
102
+ log_file_path="pkscreener-logs.txt",
103
+ filter=None,
104
+ )
93
105
 
94
106
  def calc_relative_strength(self,df:pd.DataFrame):
95
107
  if df is None or len(df) <= 1:
96
108
  return -1
97
109
  closeColumn = 'Adj Close'
98
110
  if closeColumn not in df.columns:
99
- closeColumn = 'Close'
111
+ closeColumn = "close"
100
112
 
101
113
  with pd.option_context('mode.chained_assignment', None):
102
114
  df.sort_index(inplace=True)
@@ -119,13 +131,13 @@ class ScreeningStatistics:
119
131
  if Imports["vectorbt"]:
120
132
  from vectorbt.indicators import MA as vbt
121
133
  if df is not None:
122
- ema = vbt.run(df["Close"], 1, short_name='EMA', ewm=True)
134
+ ema = vbt.run(df["close"], 1, short_name='EMA', ewm=True)
123
135
  df["Above"] = ema.ma_crossed_above(df["ATRTrailingStop"])
124
136
  df["Below"] = ema.ma_crossed_below(df["ATRTrailingStop"])
125
137
  else:
126
138
  OutputControls().printOutput(f"{colorText.FAIL}The main module needed for best Buy/Sell result calculation is missing. Falling back on an alternative, but it is not very reliable.{colorText.END}")
127
139
  if df is not None:
128
- ema = pktalib.EMA(df["Close"], ema_period) if ema_period > 1 else df["Close"]#short_name='EMA', ewm=True)
140
+ ema = pktalib.EMA(df["close"], ema_period) if ema_period > 1 else df["close"]#short_name='EMA', ewm=True)
129
141
  df["Above"] = ema > df["ATRTrailingStop"]
130
142
  df["Below"] = ema < df["ATRTrailingStop"]
131
143
  except (OSError,FileNotFoundError) as e: # pragma: no cover
@@ -160,7 +172,7 @@ class ScreeningStatistics:
160
172
  else:
161
173
  OutputControls().printOutput(msg)
162
174
  if df is not None:
163
- ema = pktalib.EMA(df["Close"], ema_period) if ema_period > 1 else df["Close"]#short_name='EMA', ewm=True)
175
+ ema = pktalib.EMA(df["close"], ema_period) if ema_period > 1 else df["close"]#short_name='EMA', ewm=True)
164
176
  df["Above"] = ema > df["ATRTrailingStop"]
165
177
  df["Below"] = ema < df["ATRTrailingStop"]
166
178
  except KeyboardInterrupt: # pragma: no cover
@@ -169,8 +181,8 @@ class ScreeningStatistics:
169
181
  pass
170
182
 
171
183
  if df is not None:
172
- df["Buy"] = (df["Close"] > df["ATRTrailingStop"]) & (df["Above"]==True)
173
- df["Sell"] = (df["Close"] < df["ATRTrailingStop"]) & (df["Below"]==True)
184
+ df["Buy"] = (df["close"] > df["ATRTrailingStop"]) & (df["Above"]==True)
185
+ df["Sell"] = (df["close"] < df["ATRTrailingStop"]) & (df["Below"]==True)
174
186
 
175
187
  return df
176
188
 
@@ -179,8 +191,8 @@ class ScreeningStatistics:
179
191
  dataframe = self.findBuySellSignalsFromATRTrailing(dataframe, key_value=2, atr_period=7, ema_period=100)
180
192
 
181
193
  # Calculate RSI and ADX
182
- rsi = pktalib.RSI(dataframe['Close'])
183
- adx = pktalib.ADX(dataframe['High'], dataframe['Low'], dataframe['Close'])
194
+ rsi = pktalib.RSI(dataframe["close"])
195
+ adx = pktalib.ADX(dataframe["high"], dataframe["low"], dataframe["close"])
184
196
 
185
197
  # Define conditions based on UTBot Alerts and additional indicators
186
198
  # ... (your custom conditions here)
@@ -233,9 +245,9 @@ class ScreeningStatistics:
233
245
  data = data.fillna(0)
234
246
  data = data.replace([np.inf, -np.inf], 0)
235
247
  one_week = 5
236
- recent = data.head(1)["High"].iloc[0]
248
+ recent = data.head(1)["high"].iloc[0]
237
249
  full52Week = data.head(50 * one_week)
238
- full52WeekHigh = full52Week["High"].max()
250
+ full52WeekHigh = full52Week["high"].max()
239
251
  # if self.shouldLog:
240
252
  # self.default_logger.debug(data.head(10))
241
253
  return recent >= full52WeekHigh
@@ -251,10 +263,10 @@ class ScreeningStatistics:
251
263
  one_week = 5
252
264
  week_52 = one_week * 50 # Considering holidays etc as well of 10 days
253
265
  full52Week = data.head(week_52 + 1).tail(week_52+1)
254
- recentHigh = data.head(1)["High"].iloc[0]
255
- recentLow = data.head(1)["Low"].iloc[0]
256
- full52WeekHigh = full52Week["High"].max()
257
- full52WeekLow = full52Week["Low"].min()
266
+ recentHigh = data.head(1)["high"].iloc[0]
267
+ recentLow = data.head(1)["low"].iloc[0]
268
+ full52WeekHigh = full52Week["high"].max()
269
+ full52WeekLow = full52Week["low"].min()
258
270
 
259
271
  saveDict["52Wk-H"] = "{:.2f}".format(full52WeekHigh)
260
272
  saveDict["52Wk-L"] = "{:.2f}".format(full52WeekLow)
@@ -287,12 +299,12 @@ class ScreeningStatistics:
287
299
  data = data.fillna(0)
288
300
  data = data.replace([np.inf, -np.inf], 0)
289
301
  one_week = 5
290
- recent = data.head(1)["Low"].iloc[0]
302
+ recent = data.head(1)["low"].iloc[0]
291
303
  last1Week = data.head(one_week)
292
304
  last2Week = data.head(2 * one_week)
293
305
  previousWeek = last2Week.tail(one_week)
294
- last1WeekLow = last1Week["Low"].min()
295
- previousWeekLow = previousWeek["Low"].min()
306
+ last1WeekLow = last1Week["low"].min()
307
+ previousWeekLow = previousWeek["low"].min()
296
308
  # if self.shouldLog:
297
309
  # self.default_logger.debug(data.head(10))
298
310
  return (recent <= min(previousWeekLow, last1WeekLow)) and (
@@ -308,14 +320,14 @@ class ScreeningStatistics:
308
320
  data = data.fillna(0)
309
321
  data = data.replace([np.inf, -np.inf], 0)
310
322
  one_week = 5
311
- recent = data.head(1)["Low"].iloc[0]
323
+ recent = data.head(1)["low"].iloc[0]
312
324
  # last1Week = data.head(one_week)
313
325
  # last2Week = data.head(2 * one_week)
314
326
  # previousWeek = last2Week.tail(one_week)
315
327
  full52Week = data.head(50 * one_week)
316
- # last1WeekLow = last1Week["Low"].min()
317
- # previousWeekLow = previousWeek["Low"].min()
318
- full52WeekLow = full52Week["Low"].min()
328
+ # last1WeekLow = last1Week["low"].min()
329
+ # previousWeekLow = previousWeek["low"].min()
330
+ full52WeekLow = full52Week["low"].min()
319
331
  # if self.shouldLog:
320
332
  # self.default_logger.debug(data.head(10))
321
333
  return recent <= full52WeekLow
@@ -329,7 +341,7 @@ class ScreeningStatistics:
329
341
  data = data.replace([np.inf, -np.inf], 0)
330
342
  period = 14
331
343
  data = data[::-1] # Reverse the dataframe so that its the oldest date first
332
- aroondf = pktalib.Aroon(data["High"], data["Low"], period)
344
+ aroondf = pktalib.Aroon(data["high"], data["low"], period)
333
345
  recent = aroondf.tail(1)
334
346
  up = recent[f"AROONU_{period}"].iloc[0]
335
347
  down = recent[f"AROOND_{period}"].iloc[0]
@@ -348,11 +360,11 @@ class ScreeningStatistics:
348
360
  recent = data.head(1)
349
361
  recentCandleHeight = self.getCandleBodyHeight(recent)
350
362
  data = data[::-1] # Reverse the dataframe so that its the oldest date first
351
- atr = pktalib.ATR(data["High"],data["Low"],data["Close"], 14)
363
+ atr = pktalib.ATR(data["high"],data["low"],data["close"], 14)
352
364
  atrCross = recentCandleHeight >= atr.tail(1).iloc[0]
353
365
  bullishRSI = recent["RSI"].iloc[0] >= 55 or recent["RSIi"].iloc[0] >= 55
354
- smav7 = pktalib.SMA(data["Volume"],timeperiod=7).tail(1).iloc[0]
355
- atrCrossCondition = atrCross and bullishRSI and (smav7 < recent["Volume"].iloc[0])
366
+ smav7 = pktalib.SMA(data["volume"],timeperiod=7).tail(1).iloc[0]
367
+ atrCrossCondition = atrCross and bullishRSI and (smav7 < recent["volume"].iloc[0])
356
368
  saveDict["ATR"] = round(atr.tail(1).iloc[0],1)
357
369
  screenDict["ATR"] = saveDict["ATR"] #(colorText.GREEN if atrCrossCondition else colorText.FAIL) + str(atr.tail(1).iloc[0]) + colorText.END
358
370
  # if self.shouldLog:
@@ -369,7 +381,7 @@ class ScreeningStatistics:
369
381
 
370
382
  SENSITIVITY = sensitivity
371
383
  # Compute ATR And nLoss variable
372
- data["xATR"] = pktalib.ATR(data["High"], data["Low"], data["Close"], timeperiod=atr_period)
384
+ data["xATR"] = pktalib.ATR(data["high"], data["low"], data["close"], timeperiod=atr_period)
373
385
  data["nLoss"] = SENSITIVITY * data["xATR"]
374
386
 
375
387
  #Drop all rows that have nan, X first depending on the ATR preiod for the moving average
@@ -380,8 +392,8 @@ class ScreeningStatistics:
380
392
 
381
393
  for i in range(1, len(data)):
382
394
  data.loc[i, "ATRTrailingStop"] = self.xATRTrailingStop_func(
383
- data.loc[i, "Close"],
384
- data.loc[i - 1, "Close"],
395
+ data.loc[i, "close"],
396
+ data.loc[i - 1, "close"],
385
397
  data.loc[i - 1, "ATRTrailingStop"],
386
398
  data.loc[i, "nLoss"],
387
399
  )
@@ -416,11 +428,11 @@ class ScreeningStatistics:
416
428
 
417
429
  # if base_count <= 4: # Maximum of 4 base candles for weekly or monthly timeframe, else 3 for daily
418
430
  # if j < len(data) and data['Candle Type'][j] == 'Rally Candle':
419
- # if data['Close'][j] > data['Low'][i] + 0.6 * data['Candle Range'][i] and data['High'][i] <= cmp:
431
+ # if data["close"][j] > data["low"][i] + 0.6 * data['Candle Range'][i] and data["high"][i] <= cmp:
420
432
  # # Check for one more rally candle or green base candle
421
433
  # k = j + 1
422
434
  # while k < len(data):
423
- # if data['Candle Type'][k] == 'Rally Candle' or (data['Candle Type'][k] == 'Base Candle' and data['Close'][k] > data['Open'][k]):
435
+ # if data['Candle Type'][k] == 'Rally Candle' or (data['Candle Type'][k] == 'Base Candle' and data["close"][k] > data["open"][k]):
424
436
  # demand_zones.append((i, j, 'Drop Base Rally', base_count))
425
437
  # drop_base_rally_zone = True
426
438
  # break
@@ -434,11 +446,11 @@ class ScreeningStatistics:
434
446
 
435
447
  # if base_count >= 1: # At least one base candle required
436
448
  # if j < len(data) and data['Candle Type'][j] == 'Rally Candle':
437
- # if data['Close'][j] > data['Close'][i] and data['High'][i] <= cmp: # New condition: close of 2nd rally candle > 1st rally candle
449
+ # if data["close"][j] > data["close"][i] and data["high"][i] <= cmp: # New condition: close of 2nd rally candle > 1st rally candle
438
450
  # # Check for one more rally candle or green base candle
439
451
  # k = j + 1
440
452
  # while k < len(data):
441
- # if data['Candle Type'][k] == 'Rally Candle' or (data['Candle Type'][k] == 'Base Candle' and data['Close'][k] > data['Open'][k]):
453
+ # if data['Candle Type'][k] == 'Rally Candle' or (data['Candle Type'][k] == 'Base Candle' and data["close"][k] > data["open"][k]):
442
454
  # demand_zones.append((i, j, 'Rally Base Rally', base_count))
443
455
  # rally_base_rally_zone = True
444
456
  # break
@@ -446,7 +458,7 @@ class ScreeningStatistics:
446
458
 
447
459
  # # Collect base candle prices for proximal line calculation
448
460
  # if data['Candle Type'][i] == 'Base Candle':
449
- # base_candle_prices.append(data['Close'][i])
461
+ # base_candle_prices.append(data["close"][i])
450
462
 
451
463
  # # Calculate proximal line price (highest price among base candles)
452
464
  # proximal_line_price = max(base_candle_prices) if base_candle_prices else None
@@ -471,12 +483,12 @@ class ScreeningStatistics:
471
483
 
472
484
  # if base_count <= 4: # Maximum of 4 base candles for weekly or monthly timeframe, else 3 for daily
473
485
  # if j < len(data) and data['Candle Type'][j] == 'Drop Candle':
474
- # if data['Close'][i] < data['Low'][j] and data['Low'][i] >= cmp: # New condition: close of drop candle < low of base candle
486
+ # if data["close"][i] < data["low"][j] and data["low"][i] >= cmp: # New condition: close of drop candle < low of base candle
475
487
  # # New logic: Look for one more drop candle or red base candle
476
488
  # k = j + 1
477
- # while k < len(data) and (data['Candle Type'][k] == 'Drop Candle' or data['Close'][k] < data['Open'][k]):
489
+ # while k < len(data) and (data['Candle Type'][k] == 'Drop Candle' or data["close"][k] < data["open"][k]):
478
490
  # k += 1
479
- # if k < len(data) and (data['Candle Type'][k] == 'Drop Candle' or data['Close'][k] < data['Open'][k]):
491
+ # if k < len(data) and (data['Candle Type'][k] == 'Drop Candle' or data["close"][k] < data["open"][k]):
480
492
  # supply_zones.append((i, j, 'Drop Base Drop', base_count))
481
493
  # drop_base_drop_zone = True
482
494
  # elif data['Candle Type'][i] == 'Rally Candle' and data['Candle Type'][i + 1] == 'Base Candle':
@@ -488,13 +500,13 @@ class ScreeningStatistics:
488
500
 
489
501
  # if base_count >= 1: # At least one base candle required
490
502
  # if j < len(data) and data['Candle Type'][j] == 'Drop Candle':
491
- # if data['Close'][j] < data['Open'][j] and data['Low'][i] >= cmp: # Modified condition: close of drop candle < open of drop candle
503
+ # if data["close"][j] < data["open"][j] and data["low"][i] >= cmp: # Modified condition: close of drop candle < open of drop candle
492
504
  # supply_zones.append((i, j, 'Rally Base Drop', base_count))
493
505
  # rally_base_drop_zone = True
494
506
 
495
507
  # # Collect base candle prices for proximal line calculation
496
508
  # if data['Candle Type'][i] == 'Base Candle':
497
- # base_candle_prices.append(data['Close'][i])
509
+ # base_candle_prices.append(data["close"][i])
498
510
 
499
511
  # # Calculate proximal line price (lowest price among base candles)
500
512
  # proximal_line_price = min(base_candle_prices) if base_candle_prices else None
@@ -504,7 +516,7 @@ class ScreeningStatistics:
504
516
  # def calculate_demand_proximal_lines(self,data, demand_zones):
505
517
  # proximal_line_prices = []
506
518
  # for start, end, _, _ in demand_zones:
507
- # base_candle_prices = data.loc[(data['Candle Type'] == 'Base Candle') & (data.index >= data.index[start]) & (data.index <= data.index[end]), ['Open', 'Close']]
519
+ # base_candle_prices = data.loc[(data['Candle Type'] == 'Base Candle') & (data.index >= data.index[start]) & (data.index <= data.index[end]), ["open", "close"]]
508
520
  # max_price = base_candle_prices.max(axis=1).max() # Get the maximum price among all base candles' open and close prices
509
521
  # proximal_line_prices.append(max_price)
510
522
  # return proximal_line_prices
@@ -512,7 +524,7 @@ class ScreeningStatistics:
512
524
  # def calculate_supply_proximal_lines(self,data, supply_zones):
513
525
  # proximal_line_prices = []
514
526
  # for start, end, _, _ in supply_zones:
515
- # base_candle_prices = data.loc[(data['Candle Type'] == 'Base Candle') & (data.index >= data.index[start]) & (data.index <= data.index[end]), ['Open', 'Close']]
527
+ # base_candle_prices = data.loc[(data['Candle Type'] == 'Base Candle') & (data.index >= data.index[start]) & (data.index <= data.index[end]), ["open", "close"]]
516
528
  # min_price = base_candle_prices.min(axis=1).min() # Get the minimum price among all base candles' open and close prices
517
529
  # proximal_line_prices.append(min_price)
518
530
  # return proximal_line_prices
@@ -522,12 +534,12 @@ class ScreeningStatistics:
522
534
  # for start, end, pattern, _ in demand_zones:
523
535
  # if pattern == 'Drop Base Rally':
524
536
  # # Logic for Drop Base Rally pattern: Take the lowest price among all components of the zone
525
- # lowest_price = min(data['Low'][start:end + 1]) # Get the lowest price within the zone
537
+ # lowest_price = min(data["low"][start:end + 1]) # Get the lowest price within the zone
526
538
  # distal_line_prices.append(lowest_price)
527
539
  # elif pattern == 'Rally Base Rally':
528
540
  # # Logic for Rally Base Rally pattern: Take the lowest of only all base candle and followed rally candle
529
- # base_candle_prices = data.loc[(data['Candle Type'] == 'Base Candle') & (data.index >= data.index[start]) & (data.index <= data.index[end]), 'Low']
530
- # rally_candle_prices = data.loc[(data['Candle Type'] == 'Rally Candle') & (data.index >= data.index[end]) & (data.index < data.index[end+1]), 'Low']
541
+ # base_candle_prices = data.loc[(data['Candle Type'] == 'Base Candle') & (data.index >= data.index[start]) & (data.index <= data.index[end]), "low"]
542
+ # rally_candle_prices = data.loc[(data['Candle Type'] == 'Rally Candle') & (data.index >= data.index[end]) & (data.index < data.index[end+1]), "low"]
531
543
  # all_prices = pd.concat([base_candle_prices, rally_candle_prices])
532
544
  # lowest_price = all_prices.min() if not all_prices.empty else None
533
545
  # distal_line_prices.append(lowest_price)
@@ -538,12 +550,12 @@ class ScreeningStatistics:
538
550
  # for start, end, pattern, _ in supply_zones:
539
551
  # if pattern == 'Rally Base Drop':
540
552
  # # Logic for Rally Base Drop pattern: Take the highest price among all components of the zone
541
- # highest_price = max(data['High'][start:end + 1]) # Get the highest price within the zone
553
+ # highest_price = max(data["high"][start:end + 1]) # Get the highest price within the zone
542
554
  # distal_line_prices.append(highest_price)
543
555
  # elif pattern == 'Drop Base Drop':
544
556
  # # Logic for Drop Base Drop pattern: Take the highest of only all base candles and followed drop candle
545
- # base_candle_prices = data.loc[(data['Candle Type'] == 'Base Candle') & (data.index >= data.index[start]) & (data.index <= data.index[end]), 'High']
546
- # drop_candle_prices = data.loc[(data['Candle Type'] == 'Drop Candle') & (data.index >= data.index[start]) & (data.index <= data.index[end]), 'High']
557
+ # base_candle_prices = data.loc[(data['Candle Type'] == 'Base Candle') & (data.index >= data.index[start]) & (data.index <= data.index[end]), "high"]
558
+ # drop_candle_prices = data.loc[(data['Candle Type'] == 'Drop Candle') & (data.index >= data.index[start]) & (data.index <= data.index[end]), "high"]
547
559
  # all_prices = pd.concat([base_candle_prices, drop_candle_prices])
548
560
  # highest_price = all_prices.max() if not all_prices.empty else None
549
561
  # distal_line_prices.append(highest_price)
@@ -563,7 +575,7 @@ class ScreeningStatistics:
563
575
  # - True if the proximal line price is tested, False otherwise
564
576
  # """
565
577
  # for i in range(end_index + 1, len(data)):
566
- # if data['Low'][i] <= proximal_line_price <= data['High'][i]:
578
+ # if data["low"][i] <= proximal_line_price <= data["high"][i]:
567
579
  # return True
568
580
  # return False
569
581
 
@@ -623,7 +635,7 @@ class ScreeningStatistics:
623
635
  # filtered_stocks = []
624
636
  # for symbol in symbol_list:
625
637
  # if data is not None:
626
- # cmp = data.iloc[-1]['Close'] # Current market price
638
+ # cmp = data.iloc[-1]["close"] # Current market price
627
639
  # demand_zones, _, _, demand_proximal_line = self.identify_demand_zone(data, cmp) # Pass cmp argument here
628
640
  # supply_zones, _, _, supply_proximal_line = self.identify_supply_zone(data, cmp) # Pass cmp argument here
629
641
 
@@ -641,7 +653,7 @@ class ScreeningStatistics:
641
653
  # with open("demand_supply_zones.txt", "w") as file:
642
654
  # for symbol in data["Stock"]:
643
655
  # if data is not None:
644
- # cmp = data.iloc[-1]['Close'] # Current market price
656
+ # cmp = data.iloc[-1]["close"] # Current market price
645
657
  # demand_zones, _, _, demand_proximal_line = self.identify_demand_zone(data, cmp)
646
658
  # supply_zones, _, _, supply_proximal_line = self.identify_supply_zone(data, cmp)
647
659
 
@@ -724,7 +736,7 @@ class ScreeningStatistics:
724
736
 
725
737
  # for symbol in filtered_stocks:
726
738
  # if data is not None:
727
- # cmp = data.iloc[-1]['Close'] # Current market price
739
+ # cmp = data.iloc[-1]["close"] # Current market price
728
740
  # demand_zones, _, _, demand_proximal_line = self.identify_demand_zone(data, cmp)
729
741
  # supply_zones, _, _, supply_proximal_line = self.identify_supply_zone(data, cmp)
730
742
 
@@ -830,9 +842,9 @@ class ScreeningStatistics:
830
842
  latestRecordsFirst_df = latestRecordsFirst_df.fillna(0)
831
843
  latestRecordsFirst_df = latestRecordsFirst_df.replace([np.inf, -np.inf], 0)
832
844
  # Bollinger bands
833
- latestRecordsFirst_df.loc[:,'BBands-U'], latestRecordsFirst_df.loc[:,'BBands-M'], latestRecordsFirst_df.loc[:,'BBands-L'] = pktalib.BBANDS(latestRecordsFirst_df["Close"], 20)
845
+ latestRecordsFirst_df.loc[:,'BBands-U'], latestRecordsFirst_df.loc[:,'BBands-M'], latestRecordsFirst_df.loc[:,'BBands-L'] = pktalib.BBANDS(latestRecordsFirst_df["close"], 20)
834
846
  # compute Keltner's channel
835
- latestRecordsFirst_df['low_kel'], latestRecordsFirst_df['upp_kel'] = pktalib.KeltnersChannel(latestRecordsFirst_df["High"], latestRecordsFirst_df["Low"],latestRecordsFirst_df["Close"],20)
847
+ latestRecordsFirst_df['low_kel'], latestRecordsFirst_df['upp_kel'] = pktalib.KeltnersChannel(latestRecordsFirst_df["high"], latestRecordsFirst_df["low"],latestRecordsFirst_df["close"],20)
836
848
  # squeeze indicator
837
849
  def in_squeeze(df):
838
850
  return df['low_kel'] < df['BBands-L'] < df['BBands-U'] < df['upp_kel']
@@ -851,8 +863,8 @@ class ScreeningStatistics:
851
863
  if filter not in [1,3,4]: # Buy/Sell/All
852
864
  return False
853
865
  # decide which action to take by comparing distances
854
- distance_to_upper = abs(latestRecordsFirst_df['BBands-U'].values[-1] - latestRecordsFirst_df['Close'].values[-1])
855
- distance_to_lower = abs(latestRecordsFirst_df['BBands-L'].values[-1] - latestRecordsFirst_df['Close'].values[-1])
866
+ distance_to_upper = abs(latestRecordsFirst_df['BBands-U'].values[-1] - latestRecordsFirst_df["close"].values[-1])
867
+ distance_to_lower = abs(latestRecordsFirst_df['BBands-L'].values[-1] - latestRecordsFirst_df["close"].values[-1])
856
868
 
857
869
  action = False
858
870
  if distance_to_upper < distance_to_lower:
@@ -892,13 +904,13 @@ class ScreeningStatistics:
892
904
  candleHeight = abs(self.getCandleBodyHeight(data[candle:]))
893
905
  totalCandleHeight += candleHeight
894
906
 
895
- reversedData.loc[:,'BBands-U'], reversedData.loc[:,'BBands-M'], reversedData.loc[:,'BBands-L'] = pktalib.BBANDS(reversedData["Close"], 20)
907
+ reversedData.loc[:,'BBands-U'], reversedData.loc[:,'BBands-M'], reversedData.loc[:,'BBands-L'] = pktalib.BBANDS(reversedData["close"], 20)
896
908
  reversedData = reversedData[::-1]
897
909
  recents = reversedData.head(6)
898
910
  ulr = self.non_zero_range(recents.loc[:,'BBands-U'], recents.loc[:,'BBands-L'])
899
911
  maxOfLast5Candles = ulr.tail(5).max()
900
912
  # bandwidth = 100 * ulr / recents.loc[:,'BBands-M']
901
- # percent = self.non_zero_range(recents.loc[:,'Close'], recents.loc[:,'BBands-L']) / ulr
913
+ # percent = self.non_zero_range(recents.loc[:,"close"], recents.loc[:,'BBands-L']) / ulr
902
914
  saveDict["bbands_ulr_ratio_max5"] = round(ulr.iloc[0]/maxOfLast5Candles,2) #percent.iloc[0]
903
915
  screenDict["bbands_ulr_ratio_max5"] = saveDict["bbands_ulr_ratio_max5"]
904
916
  # saveDict["bbands_bandwidth"] = bandwidth.iloc[0]
@@ -924,9 +936,9 @@ class ScreeningStatistics:
924
936
  data = data.replace([np.inf, -np.inf], 0)
925
937
  recent = data.head(1)
926
938
  data = data[1:]
927
- maxHigh = round(data.describe()["High"]["max"], 2)
928
- maxClose = round(data.describe()["Close"]["max"], 2)
929
- recentClose = round(recent["Close"].iloc[0], 2)
939
+ maxHigh = round(data.describe()["high"]["max"], 2)
940
+ maxClose = round(data.describe()["close"]["max"], 2)
941
+ recentClose = round(recent["close"].iloc[0], 2)
930
942
  if np.isnan(maxClose) or np.isnan(maxHigh):
931
943
  saveDict["Breakout"] = "BO: 0 R: 0"
932
944
  screenDict["Breakout"] = (
@@ -968,7 +980,7 @@ class ScreeningStatistics:
968
980
  + colorText.END
969
981
  )
970
982
  return not alreadyBrokenout
971
- noOfHigherShadows = len(data[data.High > maxClose])
983
+ noOfHigherShadows = len(data[data.high > maxClose])
972
984
  if daysToLookback / noOfHigherShadows <= 3:
973
985
  saveDict["Breakout"] = "BO: " + str(maxHigh) + " R: 0"
974
986
  if recentClose >= maxHigh:
@@ -1058,18 +1070,18 @@ class ScreeningStatistics:
1058
1070
  data = data.replace([np.inf, -np.inf], 0)
1059
1071
  reversedData = data[::-1] # Reverse the dataframe so that its the oldest date first
1060
1072
  # Find the anchor point. Find the candle where there's a major dip.
1061
- majorLow = reversedData["Low"].min()
1062
- lowRow = reversedData[reversedData["Low"] == majorLow]
1073
+ majorLow = reversedData["low"].min()
1074
+ lowRow = reversedData[reversedData["low"] == majorLow]
1063
1075
  anchored_date = lowRow.index[0]
1064
1076
  avwap = pktalib.AVWAP(df=reversedData,anchored_date=anchored_date)
1065
1077
  if 'anchored_VWAP' not in reversedData.keys():
1066
1078
  reversedData.loc[:,'anchored_VWAP'] =avwap
1067
- recentOpen = reversedData["Open"].tail(1).head(1).iloc[0]
1068
- recentClose = reversedData["Close"].tail(1).head(1).iloc[0]
1069
- recentLow = reversedData["Low"].tail(1).head(1).iloc[0]
1079
+ recentOpen = reversedData["open"].tail(1).head(1).iloc[0]
1080
+ recentClose = reversedData["close"].tail(1).head(1).iloc[0]
1081
+ recentLow = reversedData["low"].tail(1).head(1).iloc[0]
1070
1082
  recentAVWAP = reversedData["anchored_VWAP"].tail(1).head(1).iloc[0]
1071
- recentVol = reversedData["Volume"].tail(1).head(1).iloc[0]
1072
- prevVol = reversedData["Volume"].tail(2).head(1).iloc[0]
1083
+ recentVol = reversedData["volume"].tail(1).head(1).iloc[0]
1084
+ prevVol = reversedData["volume"].tail(2).head(1).iloc[0]
1073
1085
  avwap.replace(np.inf, np.nan).replace(-np.inf, np.nan).dropna(inplace=True)
1074
1086
  reversedData = reversedData.tail(len(avwap))
1075
1087
  diffFromAVWAP = (abs(recentClose-recentAVWAP)/recentAVWAP) * 100
@@ -1104,15 +1116,15 @@ class ScreeningStatistics:
1104
1116
  data = data.fillna(0)
1105
1117
  data = data.replace([np.inf, -np.inf], 0)
1106
1118
  data = data[::-1] # Reverse the dataframe so that its the oldest date first
1107
- data["RSI12"] = pktalib.RSI(data["Close"], 12)
1108
- data["EMA10"] = pktalib.EMA(data["Close"], 10)
1109
- data["EMA200"] = pktalib.EMA(data["Close"], 200)
1110
- macd = pktalib.MACD(data["Close"], 10, 18, 9)[2].tail(1)
1119
+ data["RSI12"] = pktalib.RSI(data["close"], 12)
1120
+ data["EMA10"] = pktalib.EMA(data["close"], 10)
1121
+ data["EMA200"] = pktalib.EMA(data["close"], 200)
1122
+ macd = pktalib.MACD(data["close"], 10, 18, 9)[2].tail(1)
1111
1123
  recent = data.tail(1)
1112
1124
  cond1 = recent["RSI12"].iloc[0] > 55
1113
1125
  cond2 = cond1 and (macd.iloc[:1][0] > 0)
1114
- cond3 = cond2 and (recent["Close"].iloc[0] > recent["EMA10"].iloc[0])
1115
- cond4 = cond3 and (recent["Close"].iloc[0] > recent["EMA200"].iloc[0])
1126
+ cond3 = cond2 and (recent["close"].iloc[0] > recent["EMA10"].iloc[0])
1127
+ cond4 = cond3 and (recent["close"].iloc[0] > recent["EMA200"].iloc[0])
1116
1128
  return cond4
1117
1129
 
1118
1130
  def findBuySellSignalsFromATRTrailing(self,df, key_value=1, atr_period=10, ema_period=200,buySellAll=1,saveDict=None,screenDict=None):
@@ -1124,9 +1136,9 @@ class ScreeningStatistics:
1124
1136
  data = data[::-1] # Reverse the dataframe so that its the oldest date first
1125
1137
 
1126
1138
  # Calculate ATR and xATRTrailingStop
1127
- xATR = np.array(pktalib.ATR(data['High'], data['Low'], data['Close'], timeperiod=atr_period))
1139
+ xATR = np.array(pktalib.ATR(data["high"], data["low"], data["close"], timeperiod=atr_period))
1128
1140
  nLoss = key_value * xATR
1129
- src = data['Close']
1141
+ src = data["close"]
1130
1142
  # Initialize arrays
1131
1143
  xATRTrailingStop = np.zeros(len(data))
1132
1144
  xATRTrailingStop[0] = src[0] - nLoss[0]
@@ -1148,7 +1160,7 @@ class ScreeningStatistics:
1148
1160
  pos = np.where(mask_sell, -1, pos)
1149
1161
  pos[~((pos == 1) | (pos == -1))] = 0
1150
1162
 
1151
- ema = np.array(pktalib.EMA(data['Close'], timeperiod=ema_period))
1163
+ ema = np.array(pktalib.EMA(data["close"], timeperiod=ema_period))
1152
1164
 
1153
1165
  buy_condition_utbot = (xATRTrailingStop > ema) & (pos > 0) & (src > ema)
1154
1166
  sell_condition_utbot = (xATRTrailingStop < ema) & (pos < 0) & (src < ema)
@@ -1214,9 +1226,9 @@ class ScreeningStatistics:
1214
1226
 
1215
1227
  data = data.reset_index()
1216
1228
  data['Date'] = data['Date'].apply(lambda x : x.strftime('%Y-%m-%d'))
1217
- data['Close_ch'] = data['Close'].shift(+1)
1218
- data['rpv'] = ((data['Close'] / data['Close_ch']) - 1) * data['Volume']
1219
- data['SMA50_Volume'] = data.Volume.rolling(50).mean()
1229
+ data['Close_ch'] = data["close"].shift(+1)
1230
+ data['rpv'] = ((data["close"] / data['Close_ch']) - 1) * data["volume"]
1231
+ data['SMA50_Volume'] = data.volume.rolling(50).mean()
1220
1232
  data['SMA50_rpv'] = data.rpv.rolling(50).mean()
1221
1233
 
1222
1234
  T = 0
@@ -1226,17 +1238,17 @@ class ScreeningStatistics:
1226
1238
  while t < len(data)-T:
1227
1239
  dat = data.loc[t:]
1228
1240
  Dk = dat.loc[t]['Date']
1229
- Pk = dat.loc[t]['Close']
1241
+ Pk = dat.loc[t]["close"]
1230
1242
  # search for region K to A
1231
1243
  k = 25
1232
1244
  while k > 15:
1233
1245
  #print('Searching SETUP with width = ', k)
1234
1246
  datA = dat.loc[:t+k] # Dk = t
1235
1247
  # first find absolute maxima point A
1236
- Da_index = datA[datA['Close'] == max(datA['Close'])]['Date'].index[0]
1237
- Da_value = datA[datA['Close'] == max(datA['Close'])]['Date'].values[0]
1238
- Pa_index = datA[datA['Close'] == max(datA['Close'])]['Close'].index[0]
1239
- Pa_value = datA[datA['Close'] == max(datA['Close'])]['Close'].values[0]
1248
+ Da_index = datA[datA["close"] == max(datA["close"])]['Date'].index[0]
1249
+ Da_value = datA[datA["close"] == max(datA["close"])]['Date'].values[0]
1250
+ Pa_index = datA[datA["close"] == max(datA["close"])]["close"].index[0]
1251
+ Pa_value = datA[datA["close"] == max(datA["close"])]["close"].values[0]
1240
1252
  uprv1 = abs(datA.loc[t:Da_index].loc[datA['rpv'] > 0, :]['rpv'].mean())
1241
1253
  dprv1 = abs(datA.loc[t:Da_index].loc[datA['rpv'] <= 0, :]['rpv'].mean())
1242
1254
  if (dprv1 == 'NaN') | (dprv1 == 0):
@@ -1250,11 +1262,11 @@ class ScreeningStatistics:
1250
1262
  while a > 10:
1251
1263
  #print('Lets search for LEFT SIDE CUP with width = ', a)
1252
1264
  datB = dat.loc[Da_index:Da_index+a]
1253
- Db_index = datB[datB['Close'] == min(datB['Close'])]['Date'].index[0]
1254
- Db_value = datB[datB['Close'] == min(datB['Close'])]['Date'].values[0]
1255
- Pb_index = datB[datB['Close'] == min(datB['Close'])]['Close'].index[0]
1256
- Pb_value = datB[datB['Close'] == min(datB['Close'])]['Close'].values[0]
1257
- avg_vol = datB['Volume'].mean()
1265
+ Db_index = datB[datB["close"] == min(datB["close"])]['Date'].index[0]
1266
+ Db_value = datB[datB["close"] == min(datB["close"])]['Date'].values[0]
1267
+ Pb_index = datB[datB["close"] == min(datB["close"])]["close"].index[0]
1268
+ Pb_value = datB[datB["close"] == min(datB["close"])]["close"].values[0]
1269
+ avg_vol = datB["volume"].mean()
1258
1270
  avg_ma_vol = data['SMA50_Volume'].mean()
1259
1271
  if (Pb_value < Pa_value) & (avg_vol < avg_ma_vol):
1260
1272
  #print("Voila! You found the bottom, it's all uphill from here")
@@ -1262,10 +1274,10 @@ class ScreeningStatistics:
1262
1274
  while b > round(a/3):
1263
1275
  #print("Let's search for RIGHT SIDE CUP with width = ", b)
1264
1276
  datC = dat.loc[Db_index:Db_index+b+1]
1265
- Dc_index = datC[datC['Close'] == max(datC['Close'])]['Date'].index[0]
1266
- Dc_value = datC[datC['Close'] == max(datC['Close'])]['Date'].values[0]
1267
- Pc_index = datC[datC['Close'] == max(datC['Close'])]['Close'].index[0]
1268
- Pc_value = datC[datC['Close'] == max(datC['Close'])]['Close'].values[0]
1277
+ Dc_index = datC[datC["close"] == max(datC["close"])]['Date'].index[0]
1278
+ Dc_value = datC[datC["close"] == max(datC["close"])]['Date'].values[0]
1279
+ Pc_index = datC[datC["close"] == max(datC["close"])]["close"].index[0]
1280
+ Pc_value = datC[datC["close"] == max(datC["close"])]["close"].values[0]
1269
1281
  uprv2 = abs(datC.loc[datC['rpv'] > 0, :]['rpv'].mean())
1270
1282
  dprv2 = abs(datC.loc[datC['rpv'] <= 0, :]['rpv'].mean())
1271
1283
  if (dprv2 == 'NaN') | (dprv2 == 0):
@@ -1279,10 +1291,10 @@ class ScreeningStatistics:
1279
1291
  #print("Let's search for the handle now with width = ", c)
1280
1292
  #print(t, " ", k, " ", a, " ", b, " ", c)
1281
1293
  datD = dat.loc[Dc_index:Dc_index+c+1]
1282
- Dd_index = datD[datD['Close'] == min(datD['Close'])]['Date'].index[0]
1283
- Dd_value = datD[datD['Close'] == min(datD['Close'])]['Date'].values[0]
1284
- Pd_index = datD[datD['Close'] == min(datD['Close'])]['Close'].index[0]
1285
- Pd_value = datD[datD['Close'] == min(datD['Close'])]['Close'].values[0]
1294
+ Dd_index = datD[datD["close"] == min(datD["close"])]['Date'].index[0]
1295
+ Dd_value = datD[datD["close"] == min(datD["close"])]['Date'].values[0]
1296
+ Pd_index = datD[datD["close"] == min(datD["close"])]["close"].index[0]
1297
+ Pd_value = datD[datD["close"] == min(datD["close"])]["close"].values[0]
1286
1298
  uprv3 = abs(datD.loc[datD['rpv'] > 0, :]['rpv'].mean())
1287
1299
  dprv3 = abs(datD.loc[datD['rpv'] <= 0, :]['rpv'].mean())
1288
1300
  if (dprv3 == 'NaN') | (dprv3 == 0):
@@ -1310,9 +1322,9 @@ class ScreeningStatistics:
1310
1322
 
1311
1323
  def validate_cup(self,df, cup_start, cup_bottom, cup_end):
1312
1324
  """Validate if the detected cup meets shape and depth criteria."""
1313
- start_price = df['Close'].iloc[cup_start]
1314
- bottom_price = df['Close'].iloc[cup_bottom]
1315
- end_price = df['Close'].iloc[cup_end]
1325
+ start_price = df["close"].iloc[cup_start]
1326
+ bottom_price = df["close"].iloc[cup_bottom]
1327
+ end_price = df["close"].iloc[cup_end]
1316
1328
 
1317
1329
  # Cup Depth should be reasonable (10% - 50% drop from highs)
1318
1330
  depth = (start_price - bottom_price) / start_price
@@ -1327,7 +1339,7 @@ class ScreeningStatistics:
1327
1339
 
1328
1340
  # U-shape validation (Avoiding V-bottoms)
1329
1341
  midpoint = (cup_start + cup_end) // 2
1330
- if df['Close'].iloc[midpoint] < bottom_price * 1.05:
1342
+ if df["close"].iloc[midpoint] < bottom_price * 1.05:
1331
1343
  return False
1332
1344
 
1333
1345
  return True
@@ -1337,18 +1349,18 @@ class ScreeningStatistics:
1337
1349
  avg_volatility = df['Volatility'].mean()
1338
1350
 
1339
1351
  # If volatility is high, require more data points to confirm a cup
1340
- if avg_volatility > df['Close'].mean() * 0.02:
1341
- return int(df['Close'].mean() * 0.2) + 1 # Higher volatility → require more confirmation
1342
- elif avg_volatility < df['Close'].mean() * 0.005:
1343
- return int(df['Close'].mean() * 0.05) + 1 # Lower volatility → allow faster pattern detection
1352
+ if avg_volatility > df["close"].mean() * 0.02:
1353
+ return int(df["close"].mean() * 0.2) + 1 # Higher volatility → require more confirmation
1354
+ elif avg_volatility < df["close"].mean() * 0.005:
1355
+ return int(df["close"].mean() * 0.05) + 1 # Lower volatility → allow faster pattern detection
1344
1356
  else:
1345
1357
  return 15 # Default case
1346
1358
 
1347
1359
  def validate_volume(self,df, cup_start, cup_end, handle_end):
1348
1360
  """Ensure decreasing volume in the cup and increasing volume at breakout."""
1349
- avg_cup_volume = df['Volume'].iloc[cup_start:cup_end].mean()
1350
- avg_handle_volume = df['Volume'].iloc[cup_end:handle_end].mean()
1351
- breakout_volume = df['Volume'].iloc[handle_end]
1361
+ avg_cup_volume = df["volume"].iloc[cup_start:cup_end].mean()
1362
+ avg_handle_volume = df["volume"].iloc[cup_end:handle_end].mean()
1363
+ breakout_volume = df["volume"].iloc[handle_end]
1352
1364
 
1353
1365
  return avg_cup_volume > avg_handle_volume and breakout_volume > avg_handle_volume
1354
1366
 
@@ -1358,7 +1370,7 @@ class ScreeningStatistics:
1358
1370
  from scipy.signal import argrelextrema
1359
1371
  except:
1360
1372
  return False, None
1361
- close_prices = df['Close'].values
1373
+ close_prices = df["close"].values
1362
1374
  if order <=0:
1363
1375
  order = self.get_dynamic_order(df) # Set order dynamically
1364
1376
  local_min_idx = argrelextrema(close_prices, np.less, order=order)[0] # Local minima (potential cup bottoms)
@@ -1375,19 +1387,19 @@ class ScreeningStatistics:
1375
1387
 
1376
1388
  # Handle Detection
1377
1389
  handle_start = cup_end
1378
- potential_handle = df['Close'][handle_start:handle_start+15]
1390
+ potential_handle = df["close"][handle_start:handle_start+15]
1379
1391
  handle_min = potential_handle.min()
1380
1392
  handle_end = potential_handle.idxmin()
1381
1393
 
1382
1394
  # Handle should not drop more than 50% of cup depth
1383
- cup_depth = df['Close'].iloc[cup_start] - df['Close'].iloc[cup_bottom]
1384
- handle_depth = df['Close'].iloc[handle_start] - handle_min
1395
+ cup_depth = df["close"].iloc[cup_start] - df["close"].iloc[cup_bottom]
1396
+ handle_depth = df["close"].iloc[handle_start] - handle_min
1385
1397
  if handle_depth > cup_depth * 0.5:
1386
1398
  return False,None
1387
1399
 
1388
1400
  # Breakout Confirmation
1389
- breakout_level = df['Close'].iloc[cup_start]
1390
- breakout = df[df.index > handle_end]['Close'].gt(breakout_level).any()
1401
+ breakout_level = df["close"].iloc[cup_start]
1402
+ breakout = df[df.index > handle_end]["close"].gt(breakout_level).any()
1391
1403
  if not breakout:
1392
1404
  return False,None
1393
1405
 
@@ -1423,7 +1435,7 @@ class ScreeningStatistics:
1423
1435
  recent = data.head(2)
1424
1436
  if len(recent) < 2:
1425
1437
  return False
1426
- return recent["Open"].iloc[0] > recent["High"].iloc[1]
1438
+ return recent["open"].iloc[0] > recent["high"].iloc[1]
1427
1439
 
1428
1440
  # Find stocks that opened higher than the previous high
1429
1441
  def findHigherOpens(self, df):
@@ -1435,7 +1447,7 @@ class ScreeningStatistics:
1435
1447
  recent = data.head(2)
1436
1448
  if len(recent) < 2:
1437
1449
  return False
1438
- return recent["Open"].iloc[0] > recent["Close"].iloc[1]
1450
+ return recent["open"].iloc[0] > recent["close"].iloc[1]
1439
1451
 
1440
1452
  # Find DEEL Momentum
1441
1453
  def findHighMomentum(self, df, strict=False):
@@ -1446,12 +1458,12 @@ class ScreeningStatistics:
1446
1458
  data = data.fillna(0)
1447
1459
  data = data.replace([np.inf, -np.inf], 0)
1448
1460
  data = data[::-1] # Reverse the dataframe so that its the oldest date first
1449
- mfis = pktalib.MFI(data["High"],data["Low"],data["Close"],data["Volume"], 14)
1450
- ccis = pktalib.CCI(data["High"],data["Low"],data["Close"], 14)
1451
- sma7 = pktalib.SMA(data["Close"], 7).tail(2)
1452
- sma20 = pktalib.SMA(data["Close"], 20).tail(2)
1461
+ mfis = pktalib.MFI(data["high"],data["low"],data["close"],data["volume"], 14)
1462
+ ccis = pktalib.CCI(data["high"],data["low"],data["close"], 14)
1463
+ sma7 = pktalib.SMA(data["close"], 7).tail(2)
1464
+ sma20 = pktalib.SMA(data["close"], 20).tail(2)
1453
1465
  recent = data.tail(2)
1454
- percentChange = round((recent["Close"].iloc[1] - recent["Close"].iloc[0]) *100/recent["Close"].iloc[0],1)
1466
+ percentChange = round((recent["close"].iloc[1] - recent["close"].iloc[0]) *100/recent["close"].iloc[0],1)
1455
1467
  rsi = recent["RSI"].iloc[1]
1456
1468
  mfi = mfis.tail(1).iloc[0]
1457
1469
  cci = ccis.tail(1).iloc[0]
@@ -1470,8 +1482,8 @@ class ScreeningStatistics:
1470
1482
  # RSI above 68 indicates that the stock is overbought, suggesting that it
1471
1483
  # has increased by more than 68% from its average price over the last 14 days.
1472
1484
  deelMomentum1 = percentChange >= 1 and (rsi>= 68 and mfi >= 68 and cci >= 110)
1473
- deelMomentum2 = (rsi>= 50 and mfi >= 50 and recent["Close"].iloc[1] >= sma7.iloc[1] and
1474
- recent["Close"].iloc[1] >= sma20.iloc[1]) and not strict
1485
+ deelMomentum2 = (rsi>= 50 and mfi >= 50 and recent["close"].iloc[1] >= sma7.iloc[1] and
1486
+ recent["close"].iloc[1] >= sma20.iloc[1]) and not strict
1475
1487
  hasDeelMomentum = deelMomentum1 or deelMomentum2
1476
1488
 
1477
1489
  # if self.shouldLog:
@@ -1494,8 +1506,8 @@ class ScreeningStatistics:
1494
1506
  diff_df = data[data.index >= pd.to_datetime(f'{PKDateUtilities.tradingDate().strftime(f"%Y-%m-%d")} {MarketHours().openHour:02}:{MarketHours().openMinute+self.configManager.morninganalysiscandlenumber + 2}:00+05:30', utc=True)]
1495
1507
  # brokerSqrOfftime = pd.to_datetime(f'{PKDateUtilities.tradingDate().strftime(f"%Y-%m-%d")} 15:14:00+05:30', utc=True)
1496
1508
  pass
1497
- dayHighAfterAlert = diff_df["High"].max()
1498
- highRow = diff_df[diff_df["High"] >= dayHighAfterAlert]
1509
+ dayHighAfterAlert = diff_df["high"].max()
1510
+ highRow = diff_df[diff_df["high"] >= dayHighAfterAlert]
1499
1511
  if highRow is not None and len(highRow) > 0:
1500
1512
  highRow = highRow.tail(1)
1501
1513
  return highRow.index[-1], highRow
@@ -1507,8 +1519,8 @@ class ScreeningStatistics:
1507
1519
  data = data.fillna(0)
1508
1520
  data = data.replace([np.inf, -np.inf], 0)
1509
1521
  previousDay = data.head(1)
1510
- prevDayHigh = previousDay["High"].iloc[0]
1511
- prevDayLow = previousDay["Low"].iloc[0]
1522
+ prevDayHigh = previousDay["high"].iloc[0]
1523
+ prevDayLow = previousDay["low"].iloc[0]
1512
1524
  candleDurations = [1,5,10,15,30]
1513
1525
  int_df = None
1514
1526
  hasIntradaySetup = False
@@ -1519,13 +1531,13 @@ class ScreeningStatistics:
1519
1531
  int_df = df_intraday[df_intraday.index <= pd.to_datetime(f'{PKDateUtilities.tradingDate().strftime(f"%Y-%m-%d")} {MarketHours().openHour:02}:{MarketHours().openMinute+candle1MinuteNumberSinceMarketStarted}:00+05:30', utc=True)]
1520
1532
  pass
1521
1533
  if int_df is not None and len(int_df) > 0:
1522
- combinedCandle = {"Open":self.getMorningOpen(int_df), "High":max(int_df["High"]),
1523
- "Low":min(int_df["Low"]),"Close":self.getMorningClose(int_df),
1524
- "Adj Close":int_df["Adj Close"][-1],"Volume":sum(int_df["Volume"])}
1525
- openPrice = combinedCandle["Open"]
1526
- lowPrice = combinedCandle["Low"]
1527
- closePrice = combinedCandle["Close"]
1528
- highPrice = combinedCandle["High"]
1534
+ combinedCandle = {"open":self.getMorningOpen(int_df), "high":max(int_df["high"]),
1535
+ "low":min(int_df["low"]),"close":self.getMorningClose(int_df),
1536
+ "Adj Close":int_df["Adj Close"][-1],"volume":sum(int_df["volume"])}
1537
+ openPrice = combinedCandle["open"]
1538
+ lowPrice = combinedCandle["low"]
1539
+ closePrice = combinedCandle["close"]
1540
+ highPrice = combinedCandle["high"]
1529
1541
  if buySellAll == 1 or buySellAll == 3:
1530
1542
  hasIntradaySetup = openPrice == lowPrice and openPrice < prevDayHigh and closePrice > prevDayHigh
1531
1543
  elif buySellAll == 2 or buySellAll == 3:
@@ -1544,11 +1556,11 @@ class ScreeningStatistics:
1544
1556
  data = data.fillna(0)
1545
1557
  data = data.replace([np.inf, -np.inf], 0)
1546
1558
  data = data[::-1] # Reverse the dataframe so that its the oldest date first
1547
- data_int = pd.DataFrame(data_int)['Close'].resample('30T', offset='15min').ohlc()
1559
+ data_int = pd.DataFrame(data_int)["close"].resample('30T', offset='15min').ohlc()
1548
1560
  # data_int = data_int[::-1] # Reverse the dataframe so that its the oldest date first
1549
1561
  if len(data_int) < 5: # we need TMA for period 5
1550
1562
  return False
1551
- data.loc[:,'PSAR'] = pktalib.psar(data["High"],data["Low"],acceleration=0.08)
1563
+ data.loc[:,'PSAR'] = pktalib.psar(data["high"],data["low"],acceleration=0.08)
1552
1564
  data_int.loc[:,'TMA5'] = pktalib.TriMA(data_int["close"],length=5)
1553
1565
  recent = data.tail(4)
1554
1566
  recent = recent[::-1]
@@ -1561,9 +1573,9 @@ class ScreeningStatistics:
1561
1573
  cond1 = recent["PSAR"].iloc[0] >= recent_i["TMA5"].iloc[0] and \
1562
1574
  recent["PSAR"].iloc[1] <= recent_i["TMA5"].iloc[1]
1563
1575
  # Daily volume > 1400k
1564
- cond2 = cond1 and (recent["Volume"].iloc[0] > 1400000)
1576
+ cond2 = cond1 and (recent["volume"].iloc[0] > 1400000)
1565
1577
  # Daily close above 50
1566
- cond4 = cond2 and recent["Close"].iloc[0] > 50
1578
+ cond4 = cond2 and recent["close"].iloc[0] > 50
1567
1579
  return cond4
1568
1580
 
1569
1581
  def findIPOLifetimeFirstDayBullishBreak(self, df):
@@ -1574,7 +1586,7 @@ class ScreeningStatistics:
1574
1586
  data = data.replace([np.inf, -np.inf], 0)
1575
1587
  data.dropna(axis=0, how="all", inplace=True) # Maybe there was no trade done at these times?
1576
1588
  data = data[::-1] # Reverse the dataframe so that its the oldest date first
1577
- return data["High"].iloc[0] >= data["High"].max()
1589
+ return data["high"].iloc[0] >= data["high"].max()
1578
1590
 
1579
1591
  def findMACDCrossover(self, df, afterTimestamp=None, nthCrossover=1, upDirection=True, minRSI=60):
1580
1592
  if df is None or len(df) == 0:
@@ -1584,11 +1596,11 @@ class ScreeningStatistics:
1584
1596
  data = data.replace([np.inf, -np.inf], 0)
1585
1597
  data.dropna(axis=0, how="all", inplace=True) # Maybe there was no trade done at these times?
1586
1598
  data = data[::-1] # Reverse the dataframe so that its the oldest date first
1587
- macdLine, macdSignal, macdHist = pktalib.MACD(data["Close"], 12, 26, 9)
1588
- # rsi_df = pktalib.RSI(data["Close"], 14)
1599
+ macdLine, macdSignal, macdHist = pktalib.MACD(data["close"], 12, 26, 9)
1600
+ # rsi_df = pktalib.RSI(data["close"], 14)
1589
1601
  line_df = pd.DataFrame(macdLine)
1590
1602
  signal_df = pd.DataFrame(macdSignal)
1591
- vol_df = data["Volume"]
1603
+ vol_df = data["volume"]
1592
1604
  diff_df = pd.concat([line_df, signal_df, signal_df-line_df,vol_df], axis=1)
1593
1605
  diff_df.columns = ["line","signal","diff","vol"]
1594
1606
  diff_df = diff_df[diff_df["vol"] > 0] # We're not going to do anything with a candle where there was no trade.
@@ -1626,27 +1638,27 @@ class ScreeningStatistics:
1626
1638
  return False
1627
1639
  data = df.copy()
1628
1640
  # https://chartink.com/screener/nr4-daily-today
1629
- if data.tail(1)["Volume"].iloc[0] <= 50000:
1641
+ if data.tail(1)["volume"].iloc[0] <= 50000:
1630
1642
  return False
1631
1643
  data = data.fillna(0)
1632
1644
  data = data.replace([np.inf, -np.inf], 0)
1633
1645
  data = data[::-1] # Reverse the dataframe so that its the oldest date first
1634
- data["SMA10"] = pktalib.SMA(data["Close"], 10)
1635
- data["SMA50"] = pktalib.SMA(data["Close"], 50)
1636
- data["SMA200"] = pktalib.SMA(data["Close"], 200)
1646
+ data["SMA10"] = pktalib.SMA(data["close"], 10)
1647
+ data["SMA50"] = pktalib.SMA(data["close"], 50)
1648
+ data["SMA200"] = pktalib.SMA(data["close"], 200)
1637
1649
  recent = data.tail(5)
1638
1650
  recent = recent[::-1]
1639
- cond1 = (recent["High"].iloc[0] - recent["Low"].iloc[0]) < (
1640
- recent["High"].iloc[1] - recent["Low"].iloc[1]
1651
+ cond1 = (recent["high"].iloc[0] - recent["low"].iloc[0]) < (
1652
+ recent["high"].iloc[1] - recent["low"].iloc[1]
1641
1653
  )
1642
- cond2 = cond1 and (recent["High"].iloc[0] - recent["Low"].iloc[0]) < (
1643
- recent["High"].iloc[2] - recent["Low"].iloc[2]
1654
+ cond2 = cond1 and (recent["high"].iloc[0] - recent["low"].iloc[0]) < (
1655
+ recent["high"].iloc[2] - recent["low"].iloc[2]
1644
1656
  )
1645
- cond3 = cond2 and (recent["High"].iloc[0] - recent["Low"].iloc[0]) < (
1646
- recent["High"].iloc[3] - recent["Low"].iloc[3]
1657
+ cond3 = cond2 and (recent["high"].iloc[0] - recent["low"].iloc[0]) < (
1658
+ recent["high"].iloc[3] - recent["low"].iloc[3]
1647
1659
  )
1648
- cond4 = cond3 and (recent["High"].iloc[0] - recent["Low"].iloc[0]) < (
1649
- recent["High"].iloc[4] - recent["Low"].iloc[4]
1660
+ cond4 = cond3 and (recent["high"].iloc[0] - recent["low"].iloc[0]) < (
1661
+ recent["high"].iloc[4] - recent["low"].iloc[4]
1650
1662
  )
1651
1663
  cond5 = cond4 and (recent["SMA10"].iloc[0] > recent["SMA50"].iloc[0])
1652
1664
  cond6 = cond5 and (recent["SMA50"].iloc[0] > recent["SMA200"].iloc[0])
@@ -1659,22 +1671,22 @@ class ScreeningStatistics:
1659
1671
  data = data.fillna(0)
1660
1672
  data = data.replace([np.inf, -np.inf], 0)
1661
1673
  data = data[::-1] # Reverse the dataframe so that its the oldest date first
1662
- data.loc[:,'BBands-U'], data.loc[:,'BBands-M'], data.loc[:,'BBands-L'] = pktalib.BBANDS(data["Close"], 20)
1674
+ data.loc[:,'BBands-U'], data.loc[:,'BBands-M'], data.loc[:,'BBands-L'] = pktalib.BBANDS(data["close"], 20)
1663
1675
  recent = data.tail(4)
1664
1676
  recent = recent[::-1]
1665
1677
  if len(recent) < 4:
1666
1678
  return False
1667
1679
  # 1 day ago high > 2 days ago high
1668
- cond1 = recent["High"].iloc[1] > recent["High"].iloc[2]
1680
+ cond1 = recent["high"].iloc[1] > recent["high"].iloc[2]
1669
1681
  # 1 day ago close < 2 days ago high
1670
- cond2 = cond1 and (recent["Close"].iloc[1] < recent["High"].iloc[2])
1682
+ cond2 = cond1 and (recent["close"].iloc[1] < recent["high"].iloc[2])
1671
1683
  # 1 day ago volume > 3 days ago volume
1672
- cond3 = cond2 and (recent["Volume"].iloc[1] > recent["Volume"].iloc[3])
1684
+ cond3 = cond2 and (recent["volume"].iloc[1] > recent["volume"].iloc[3])
1673
1685
  # daily high < 1 day ago high
1674
- cond4 = cond3 and (recent["High"].iloc[0] < recent["High"].iloc[1])
1686
+ cond4 = cond3 and (recent["high"].iloc[0] < recent["high"].iloc[1])
1675
1687
  # daily close crossed below daily lower bollinger band(20,2)
1676
- cond5 = cond4 and (recent["Close"].iloc[0] <= recent["BBands-L"].iloc[0] and \
1677
- recent["Close"].iloc[1] >= recent["BBands-L"].iloc[1])
1688
+ cond5 = cond4 and (recent["close"].iloc[0] <= recent["BBands-L"].iloc[0] and \
1689
+ recent["close"].iloc[1] >= recent["BBands-L"].iloc[1])
1678
1690
  return cond5
1679
1691
 
1680
1692
  # Find potential breakout stocks
@@ -1691,17 +1703,17 @@ class ScreeningStatistics:
1691
1703
  data = data.replace([np.inf, -np.inf], 0)
1692
1704
  data = data.head(231)
1693
1705
  recent = data.head(1)
1694
- recentVolume = recent["Volume"].iloc[0]
1695
- recentClose = round(recent["Close"].iloc[0] * 1.05, 2)
1696
- highestHigh200 = round(data.head(201).tail(200).describe()["High"]["max"], 2)
1697
- highestHigh30 = round(data.head(31).tail(30).describe()["High"]["max"], 2)
1698
- highestHigh200From30 = round(data.tail(200).describe()["High"]["max"], 2)
1699
- highestHigh8From30 = round(data.head(39).tail(8).describe()["High"]["max"], 2)
1706
+ recentVolume = recent["volume"].iloc[0]
1707
+ recentClose = round(recent["close"].iloc[0] * 1.05, 2)
1708
+ highestHigh200 = round(data.head(201).tail(200).describe()["high"]["max"], 2)
1709
+ highestHigh30 = round(data.head(31).tail(30).describe()["high"]["max"], 2)
1710
+ highestHigh200From30 = round(data.tail(200).describe()["high"]["max"], 2)
1711
+ highestHigh8From30 = round(data.head(39).tail(8).describe()["high"]["max"], 2)
1700
1712
  data = data.head(200)
1701
1713
  data = data[::-1] # Reverse the dataframe so that its the oldest date first
1702
- vol200 = pktalib.SMA(data["Volume"],timeperiod=200)
1714
+ vol200 = pktalib.SMA(data["volume"],timeperiod=200)
1703
1715
  data["SMA200V"] = vol200
1704
- vol50 = pktalib.SMA(data["Volume"],timeperiod=50)
1716
+ vol50 = pktalib.SMA(data["volume"],timeperiod=50)
1705
1717
  data["SMA50V"] = vol50
1706
1718
  recent = data.tail(1)
1707
1719
  sma200v = recent["SMA200V"].iloc[0]
@@ -1731,7 +1743,7 @@ class ScreeningStatistics:
1731
1743
  return False
1732
1744
 
1733
1745
  def findPriceActionCross(self, df, ma, daysToConsider=1, baseMAOrPrice=None, isEMA=False,maDirectionFromBelow=True):
1734
- ma_val = pktalib.EMA(df["Close"],int(ma)) if isEMA else pktalib.SMA(df["Close"],int(ma))
1746
+ ma_val = pktalib.EMA(df["close"],int(ma)) if isEMA else pktalib.SMA(df["close"],int(ma))
1735
1747
  ma = ma_val.tail(daysToConsider).head(1).iloc[0]
1736
1748
  ma_prev = ma_val.tail(daysToConsider+1).head(1).iloc[0]
1737
1749
  base = baseMAOrPrice.tail(daysToConsider).head(1).iloc[0]
@@ -1754,13 +1766,13 @@ class ScreeningStatistics:
1754
1766
  if len(recent) < 4:
1755
1767
  return False
1756
1768
  # 1 day ago high > 2 days ago high
1757
- cond1 = recent["High"].iloc[1] > recent["High"].iloc[2]
1769
+ cond1 = recent["high"].iloc[1] > recent["high"].iloc[2]
1758
1770
  # daily close < 1 day ago high
1759
- cond2 = cond1 and (recent["Close"].iloc[0] < recent["High"].iloc[1])
1771
+ cond2 = cond1 and (recent["close"].iloc[0] < recent["high"].iloc[1])
1760
1772
  # Daily volume > 3 days ago volume
1761
- cond3 = cond2 and (recent["Volume"].iloc[0] > recent["Volume"].iloc[3])
1773
+ cond3 = cond2 and (recent["volume"].iloc[0] > recent["volume"].iloc[3])
1762
1774
  # daily high < 1 day ago high
1763
- cond4 = cond3 and (recent["High"].iloc[0] < recent["High"].iloc[1])
1775
+ cond4 = cond3 and (recent["high"].iloc[0] < recent["high"].iloc[1])
1764
1776
  return cond4
1765
1777
 
1766
1778
  # Find stocks with reversing PSAR and RSI
@@ -1769,7 +1781,7 @@ class ScreeningStatistics:
1769
1781
  return False
1770
1782
  data = df.copy()
1771
1783
  data = data[::-1]
1772
- psar = pktalib.psar(data["High"],data["Low"])
1784
+ psar = pktalib.psar(data["high"],data["low"])
1773
1785
  if len(psar) < 3:
1774
1786
  return False
1775
1787
  psar = psar.tail(3)
@@ -1777,9 +1789,9 @@ class ScreeningStatistics:
1777
1789
  # dayMinus2Psar = psar.iloc[0]
1778
1790
  dayMinus1Psar = psar.iloc[1]
1779
1791
  dayPSAR = psar.iloc[2]
1780
- # dayMinus2Close = data["Close"].iloc[0]
1781
- dayMinus1Close = data["Close"].iloc[1]
1782
- dayClose = data["Close"].iloc[2]
1792
+ # dayMinus2Close = data["close"].iloc[0]
1793
+ dayMinus1Close = data["close"].iloc[1]
1794
+ dayClose = data["close"].iloc[2]
1783
1795
  # dayMinus2RSI = data["RSI"].iloc[0]
1784
1796
  dayMinus1RSI = data["RSI"].iloc[1]
1785
1797
  dayRSI = data["RSI"].iloc[2]
@@ -1818,9 +1830,9 @@ class ScreeningStatistics:
1818
1830
  for maLength in maRange:
1819
1831
  dataCopy = data
1820
1832
  if self.configManager.useEMA or maLength == 9:
1821
- maRev = pktalib.EMA(dataCopy["Close"], timeperiod=maLength)
1833
+ maRev = pktalib.EMA(dataCopy["close"], timeperiod=maLength)
1822
1834
  else:
1823
- maRev = pktalib.MA(dataCopy["Close"], timeperiod=maLength)
1835
+ maRev = pktalib.MA(dataCopy["close"], timeperiod=maLength)
1824
1836
  try:
1825
1837
  dataCopy.drop("maRev", axis=1, inplace=True, errors="ignore")
1826
1838
  except KeyboardInterrupt: # pragma: no cover
@@ -1832,11 +1844,11 @@ class ScreeningStatistics:
1832
1844
  bullishMAReversal = dataCopy["maRev"].iloc[0] >= dataCopy["maRev"].iloc[1] and \
1833
1845
  dataCopy["maRev"].iloc[1] >= dataCopy["maRev"].iloc[2] and \
1834
1846
  dataCopy["maRev"].iloc[2] < dataCopy["maRev"].iloc[3]
1835
- bullishClose = dataCopy.head(1)["Close"].iloc[0] >= dataCopy.head(1)["maRev"].iloc[0]
1847
+ bullishClose = dataCopy.head(1)["close"].iloc[0] >= dataCopy.head(1)["maRev"].iloc[0]
1836
1848
  bearishMAReversal = dataCopy["maRev"].iloc[0] <= dataCopy["maRev"].iloc[1] and \
1837
1849
  dataCopy["maRev"].iloc[1] <= dataCopy["maRev"].iloc[2] and \
1838
1850
  dataCopy["maRev"].iloc[2] > dataCopy["maRev"].iloc[3]
1839
- isRecentCloseWithinPercentRange = dataCopy.equals(dataCopy[(dataCopy.Close >= (dataCopy.maRev - (dataCopy.maRev * percentage))) & (dataCopy.Close <= (dataCopy.maRev + (dataCopy.maRev * percentage)))])
1851
+ isRecentCloseWithinPercentRange = dataCopy.equals(dataCopy[(dataCopy.close >= (dataCopy.maRev - (dataCopy.maRev * percentage))) & (dataCopy.close <= (dataCopy.maRev + (dataCopy.maRev * percentage)))])
1840
1852
  if (isRecentCloseWithinPercentRange and bullishClose and bullishMAReversal) or \
1841
1853
  (isRecentCloseWithinPercentRange and not bullishClose and bearishMAReversal):
1842
1854
  hasReversals = True
@@ -1906,7 +1918,7 @@ class ScreeningStatistics:
1906
1918
  if df is None or len(df) == 0 or len(df) < 144:
1907
1919
  return 0
1908
1920
  # RVM over the lookback period of 15 periods
1909
- rvm = pktalib.RVM(df["High"],df["Low"],df["Close"],15)
1921
+ rvm = pktalib.RVM(df["high"],df["low"],df["close"],15)
1910
1922
  screenDict["RVM(15)"] = rvm
1911
1923
  saveDict["RVM(15)"] = rvm
1912
1924
  return rvm
@@ -1918,20 +1930,20 @@ class ScreeningStatistics:
1918
1930
  data = data.fillna(0)
1919
1931
  data = data.replace([np.inf, -np.inf], 0)
1920
1932
  data = data[::-1] # Reverse the dataframe so that its the oldest date first
1921
- data.loc[:,'SMAV10'] = pktalib.SMA(data["Volume"], 10)
1933
+ data.loc[:,'SMAV10'] = pktalib.SMA(data["volume"], 10)
1922
1934
  recent = data.tail(4)
1923
1935
  recent = recent[::-1]
1924
1936
  if len(recent) < 4:
1925
1937
  return False
1926
1938
  # daily close < 1 day ago close * .97
1927
- cond1 = recent["Close"].iloc[0] < recent["Close"].iloc[1] * 0.97
1939
+ cond1 = recent["close"].iloc[0] < recent["close"].iloc[1] * 0.97
1928
1940
  # Daily volume > 100k
1929
- cond2 = cond1 and (recent["Volume"].iloc[0] > 100000)
1941
+ cond2 = cond1 and (recent["volume"].iloc[0] > 100000)
1930
1942
  # Daily volume * Daily Close > 1000k
1931
- cond3 = cond2 and (recent["Volume"].iloc[0] * recent["Close"].iloc[0] > 1000000)
1943
+ cond3 = cond2 and (recent["volume"].iloc[0] * recent["close"].iloc[0] > 1000000)
1932
1944
  # Daily close above 8
1933
- cond4 = cond3 and recent["Close"].iloc[0] > 8
1934
- cond5 = cond4 and (recent["Volume"].iloc[0] > recent["SMAV10"].iloc[0] * 0.75)
1945
+ cond4 = cond3 and recent["close"].iloc[0] > 8
1946
+ cond5 = cond4 and (recent["volume"].iloc[0] > recent["SMAV10"].iloc[0] * 0.75)
1935
1947
  return cond5
1936
1948
 
1937
1949
  def findSuperGainersLosers(self, df, percentChangeRequired=15, gainer=True):
@@ -1942,7 +1954,7 @@ class ScreeningStatistics:
1942
1954
  data = data.replace([np.inf, -np.inf], 0)
1943
1955
  data = data[::-1] # Reverse the dataframe so that its the oldest date first
1944
1956
  recent = data.tail(2)
1945
- percentChange = round((recent["Close"].iloc[1] - recent["Close"].iloc[0]) *100/recent["Close"].iloc[0],1)
1957
+ percentChange = round((recent["close"].iloc[1] - recent["close"].iloc[0]) *100/recent["close"].iloc[0],1)
1946
1958
  return percentChange >= percentChangeRequired if gainer else percentChange <= percentChangeRequired
1947
1959
 
1948
1960
  #@measure_time
@@ -1961,10 +1973,10 @@ class ScreeningStatistics:
1961
1973
  saved = self.findCurrentSavedValue(screenDict,saveDict,"Trend")
1962
1974
  try:
1963
1975
  with SuppressOutput(suppress_stdout=True, suppress_stderr=True):
1964
- data["tops"] = data["Close"].iloc[
1976
+ data["tops"] = data["close"].iloc[
1965
1977
  list(
1966
1978
  pktalib.argrelextrema(
1967
- np.array(data["Close"]), np.greater_equal, order=1
1979
+ np.array(data["close"]), np.greater_equal, order=1
1968
1980
  )[0]
1969
1981
  )
1970
1982
  ]
@@ -2046,16 +2058,16 @@ class ScreeningStatistics:
2046
2058
 
2047
2059
  """ Ignoring the Resitance for long-term purpose
2048
2060
  while len(data_high) > points:
2049
- slope, intercept, r_value, p_value, std_err = linregress(x=data_high['Number'], y=data_high['High'])
2050
- data_high = data_high.loc[data_high['High'] > slope * data_high['Number'] + intercept]
2051
- slope, intercept, r_value, p_value, std_err = linregress(x=data_high['Number'], y=data_high['Close'])
2061
+ slope, intercept, r_value, p_value, std_err = linregress(x=data_high['Number'], y=data_high["high"])
2062
+ data_high = data_high.loc[data_high["high"] > slope * data_high['Number'] + intercept]
2063
+ slope, intercept, r_value, p_value, std_err = linregress(x=data_high['Number'], y=data_high["close"])
2052
2064
  data['Resistance'] = slope * data['Number'] + intercept
2053
2065
  """
2054
2066
 
2055
2067
  while len(data_low) > points:
2056
2068
  try:
2057
2069
  slope, intercept, r_value, p_value, std_err = linregress(
2058
- x=data_low["Number"], y=data_low["Low"]
2070
+ x=data_low["Number"], y=data_low["low"]
2059
2071
  )
2060
2072
  except KeyboardInterrupt: # pragma: no cover
2061
2073
  raise KeyboardInterrupt
@@ -2063,11 +2075,11 @@ class ScreeningStatistics:
2063
2075
  self.default_logger.debug(e, exc_info=True)
2064
2076
  continue
2065
2077
  data_low = data_low.loc[
2066
- data_low["Low"] < slope * data_low["Number"] + intercept
2078
+ data_low["low"] < slope * data_low["Number"] + intercept
2067
2079
  ]
2068
2080
 
2069
2081
  slope, intercept, r_value, p_value, std_err = linregress(
2070
- x=data_low["Number"], y=data_low["Close"]
2082
+ x=data_low["Number"], y=data_low["close"]
2071
2083
  )
2072
2084
  data["Support"] = slope * data["Number"] + intercept
2073
2085
  now = data.tail(1)
@@ -2075,7 +2087,7 @@ class ScreeningStatistics:
2075
2087
  limit_upper = now["Support"].iloc[0] + (now["Support"].iloc[0] * percentage)
2076
2088
  limit_lower = now["Support"].iloc[0] - (now["Support"].iloc[0] * percentage)
2077
2089
  saved = self.findCurrentSavedValue(screenDict, saveDict, "Pattern")
2078
- if limit_lower < now["Close"].iloc[0] < limit_upper and slope > 0.15:
2090
+ if limit_lower < now["close"].iloc[0] < limit_upper and slope > 0.15:
2079
2091
  screenDict["Pattern"] = (
2080
2092
  saved[0] + colorText.GREEN + "Trendline-Support" + colorText.END
2081
2093
  )
@@ -2088,7 +2100,7 @@ class ScreeningStatistics:
2088
2100
  color = 'tab:green'
2089
2101
  xdate = [x.date() for x in data.index]
2090
2102
  ax1.set_xlabel('Date', color=color)
2091
- ax1.plot(xdate, data.Close, label="close", color=color)
2103
+ ax1.plot(xdate, data.close, label="close", color=color)
2092
2104
  ax1.tick_params(axis='x', labelcolor=color)
2093
2105
 
2094
2106
  ax2 = ax1.twiny() # ax2 and ax1 will have common y axis and different x axis, twiny
@@ -2118,14 +2130,14 @@ class ScreeningStatistics:
2118
2130
  try:
2119
2131
  data = df.copy()
2120
2132
  data = data[::-1]
2121
- today_sma = pktalib.SMA(data["Close"], timeperiod=50)
2122
- sma_minus9 = pktalib.SMA(data.head(len(data)-9)["Close"], timeperiod=50)
2123
- sma_minus14 = pktalib.SMA(data.head(len(data)-14)["Close"], timeperiod=50)
2124
- sma_minus20 = pktalib.SMA(data.head(len(data)-20)["Close"], timeperiod=50)
2125
- today_lma = pktalib.SMA(data["Close"], timeperiod=200)
2126
- lma_minus20 = pktalib.SMA(data.head(len(data)-20)["Close"], timeperiod=200)
2127
- lma_minus80 = pktalib.SMA(data.head(len(data)-80)["Close"], timeperiod=200)
2128
- lma_minus100 = pktalib.SMA(data.head(len(data)-100)["Close"], timeperiod=200)
2133
+ today_sma = pktalib.SMA(data["close"], timeperiod=50)
2134
+ sma_minus9 = pktalib.SMA(data.head(len(data)-9)["close"], timeperiod=50)
2135
+ sma_minus14 = pktalib.SMA(data.head(len(data)-14)["close"], timeperiod=50)
2136
+ sma_minus20 = pktalib.SMA(data.head(len(data)-20)["close"], timeperiod=50)
2137
+ today_lma = pktalib.SMA(data["close"], timeperiod=200)
2138
+ lma_minus20 = pktalib.SMA(data.head(len(data)-20)["close"], timeperiod=200)
2139
+ lma_minus80 = pktalib.SMA(data.head(len(data)-80)["close"], timeperiod=200)
2140
+ lma_minus100 = pktalib.SMA(data.head(len(data)-100)["close"], timeperiod=200)
2129
2141
  today_lma = today_lma.iloc[len(today_lma)-1] if today_lma is not None else 0
2130
2142
  lma_minus20 = lma_minus20.iloc[len(lma_minus20)-1] if lma_minus20 is not None else 0
2131
2143
  lma_minus80 = lma_minus80.iloc[len(lma_minus80)-1] if lma_minus80 is not None else 0
@@ -2229,13 +2241,13 @@ class ScreeningStatistics:
2229
2241
  return isUptrend, mf_inst_ownershipChange, fairValueDiff
2230
2242
 
2231
2243
  def getCandleBodyHeight(self, dailyData):
2232
- bodyHeight = dailyData["Close"].iloc[0] - dailyData["Open"].iloc[0]
2244
+ bodyHeight = dailyData["close"].iloc[0] - dailyData["open"].iloc[0]
2233
2245
  return bodyHeight
2234
2246
 
2235
2247
  # Private method to find candle type
2236
2248
  # True = Bullish, False = Bearish
2237
2249
  def getCandleType(self, dailyData):
2238
- return bool(dailyData["Close"].iloc[0] >= dailyData["Open"].iloc[0])
2250
+ return bool(dailyData["close"].iloc[0] >= dailyData["open"].iloc[0])
2239
2251
 
2240
2252
  def getFairValue(self, stock, hostData=None, force=False,exchangeName="INDIA"):
2241
2253
  if hostData is None or len(hostData) < 1:
@@ -2336,18 +2348,18 @@ class ScreeningStatistics:
2336
2348
  return netChangeMF,netChangeInst,latest_mfdate,latest_instdate
2337
2349
 
2338
2350
  def getMorningClose(self,df):
2339
- close = df["Close"][-1]
2351
+ close = df["close"][-1]
2340
2352
  index = len(df)
2341
2353
  while close is np.nan and index >= 0:
2342
- close = df["Close"][index - 1]
2354
+ close = df["close"][index - 1]
2343
2355
  index -= 1
2344
2356
  return close
2345
2357
 
2346
2358
  def getMorningOpen(self,df):
2347
- open = df["Open"][0]
2359
+ open = df["open"][0]
2348
2360
  index = 0
2349
2361
  while open is np.nan and index < len(df):
2350
- open = df["Open"][index + 1]
2362
+ open = df["open"][index + 1]
2351
2363
  index += 1
2352
2364
  return open
2353
2365
 
@@ -2451,10 +2463,10 @@ class ScreeningStatistics:
2451
2463
  with SuppressOutput(suppress_stderr=True, suppress_stdout=True):
2452
2464
  data = data[pkl["columns"]]
2453
2465
  ### v2 Preprocessing
2454
- data["High"] = data["High"].pct_change() * 100
2455
- data["Low"] = data["Low"].pct_change() * 100
2456
- data["Open"] = data["Open"].pct_change() * 100
2457
- data["Close"] = data["Close"].pct_change() * 100
2466
+ data["high"] = data["high"].pct_change() * 100
2467
+ data["low"] = data["low"].pct_change() * 100
2468
+ data["open"] = data["open"].pct_change() * 100
2469
+ data["close"] = data["close"].pct_change() * 100
2458
2470
  data = data.iloc[-1]
2459
2471
  ###
2460
2472
  data = pkl["scaler"].transform([data])
@@ -2512,47 +2524,47 @@ class ScreeningStatistics:
2512
2524
  data = data.replace([np.inf, -np.inf], 0)
2513
2525
  data.reset_index(inplace=True)
2514
2526
  data.rename(columns={"index": "Date"}, inplace=True)
2515
- data = data[data["High"]>0]
2516
- data = data[data["Low"]>0]
2517
- data["tops"] = (data["High"].iloc[list(pktalib.argrelextrema(np.array(data["High"]), np.greater_equal, order=window)[0])].head(numTopsBottoms))
2518
- data["bots"] = (data["Low"].iloc[list(pktalib.argrelextrema(np.array(data["Low"]), np.less_equal, order=window)[0])].head(numTopsBottoms))
2527
+ data = data[data["high"]>0]
2528
+ data = data[data["low"]>0]
2529
+ data["tops"] = (data["high"].iloc[list(pktalib.argrelextrema(np.array(data["high"]), np.greater_equal, order=window)[0])].head(numTopsBottoms))
2530
+ data["bots"] = (data["low"].iloc[list(pktalib.argrelextrema(np.array(data["low"]), np.less_equal, order=window)[0])].head(numTopsBottoms))
2519
2531
  tops = data[data.tops > 0]
2520
2532
  bots = data[data.bots > 0]
2521
2533
  return tops, bots
2522
2534
 
2523
2535
  def monitorFiveEma(self, fetcher, result_df, last_signal, risk_reward=3):
2524
- col_names = ["High", "Low", "Close", "5EMA"]
2536
+ col_names = ["high", "low", "close", "5EMA"]
2525
2537
  data_list = ["nifty_buy", "banknifty_buy", "nifty_sell", "banknifty_sell"]
2526
2538
 
2527
2539
  data_tuple = fetcher.fetchFiveEmaData()
2528
2540
  for cnt in range(len(data_tuple)):
2529
2541
  d = data_tuple[cnt]
2530
- d["5EMA"] = pktalib.EMA(d["Close"], timeperiod=5)
2542
+ d["5EMA"] = pktalib.EMA(d["close"], timeperiod=5)
2531
2543
  d = d[col_names]
2532
2544
  d = d.dropna().round(2)
2533
2545
 
2534
2546
  with SuppressOutput(suppress_stderr=True, suppress_stdout=True):
2535
2547
  if "sell" in data_list[cnt]:
2536
- streched = d[(d.Low > d["5EMA"]) & (d.Low - d["5EMA"] > 0.5)]
2537
- streched["SL"] = streched.High
2548
+ streched = d[(d.low > d["5EMA"]) & (d.low - d["5EMA"] > 0.5)]
2549
+ streched["SL"] = streched.high
2538
2550
  validate = d[
2539
- (d.Low.shift(1) > d["5EMA"].shift(1))
2540
- & (d.Low.shift(1) - d["5EMA"].shift(1) > 0.5)
2551
+ (d.low.shift(1) > d["5EMA"].shift(1))
2552
+ & (d.low.shift(1) - d["5EMA"].shift(1) > 0.5)
2541
2553
  ]
2542
2554
  old_index = validate.index
2543
2555
  else:
2544
- mask = (d.High < d["5EMA"]) & (d["5EMA"] - d.High > 0.5) # Buy
2556
+ mask = (d.high < d["5EMA"]) & (d["5EMA"] - d.high > 0.5) # Buy
2545
2557
  streched = d[mask]
2546
- streched["SL"] = streched.Low
2558
+ streched["SL"] = streched.low
2547
2559
  validate = d.loc[mask.shift(1).fillna(False)]
2548
2560
  old_index = validate.index
2549
2561
  tgt = pd.DataFrame(
2550
2562
  (
2551
- validate.Close.reset_index(drop=True)
2563
+ validate.close.reset_index(drop=True)
2552
2564
  - (
2553
2565
  (
2554
2566
  streched.SL.reset_index(drop=True)
2555
- - validate.Close.reset_index(drop=True)
2567
+ - validate.close.reset_index(drop=True)
2556
2568
  )
2557
2569
  * risk_reward
2558
2570
  )
@@ -2570,9 +2582,9 @@ class ScreeningStatistics:
2570
2582
  validate = validate.tail(len(old_index))
2571
2583
  validate = validate.set_index(old_index)
2572
2584
  if "sell" in data_list[cnt]:
2573
- final = validate[validate.Close < validate["5EMA"]].tail(1)
2585
+ final = validate[validate.close < validate["5EMA"]].tail(1)
2574
2586
  else:
2575
- final = validate[validate.Close > validate["5EMA"]].tail(1)
2587
+ final = validate[validate.close > validate["5EMA"]].tail(1)
2576
2588
 
2577
2589
  if data_list[cnt] not in last_signal:
2578
2590
  last_signal[data_list[cnt]] = final
@@ -2639,7 +2651,7 @@ class ScreeningStatistics:
2639
2651
  return result_df[::-1]
2640
2652
 
2641
2653
  def non_zero_range(self, high: pd.Series, low: pd.Series) -> pd.Series:
2642
- """Returns the difference of two series and adds epsilon to any zero values. This occurs commonly in crypto data when 'high' = 'low'."""
2654
+ """Returns the difference of two series and adds epsilon to any zero values. This occurs commonly in crypto data when "high" = "low"."""
2643
2655
  diff = high - low
2644
2656
  if diff.eq(0).any().any():
2645
2657
  diff += sflt.epsilon
@@ -2652,8 +2664,8 @@ class ScreeningStatistics:
2652
2664
  (dataframe['adx'] > self.adx_long_min.value) & # trend strength confirmation
2653
2665
  (dataframe['adx'] < self.adx_long_max.value) & # trend strength confirmation
2654
2666
  (dataframe['trend_l'] > 0) &
2655
- (dataframe['volume'] > dataframe['volume_mean']) &
2656
- (dataframe['volume'] > 0)
2667
+ (dataframe["volume"] > dataframe['volume_mean']) &
2668
+ (dataframe["volume"] > 0)
2657
2669
 
2658
2670
  ),
2659
2671
  'enter_long'] = 1
@@ -2663,7 +2675,7 @@ class ScreeningStatistics:
2663
2675
  (dataframe['adx'] > self.adx_short_min.value) & # trend strength confirmation
2664
2676
  (dataframe['adx'] < self.adx_short_max.value) & # trend strength confirmation
2665
2677
  (dataframe['trend_s'] < 0) &
2666
- (dataframe['volume'] > dataframe['volume_mean_s']) # volume weighted indicator
2678
+ (dataframe["volume"] > dataframe['volume_mean_s']) # volume weighted indicator
2667
2679
  ),
2668
2680
  'enter_short'] = 1
2669
2681
 
@@ -2676,15 +2688,15 @@ class ScreeningStatistics:
2676
2688
  dataframe.loc[:, 'exit_tag'] = ''
2677
2689
 
2678
2690
  exit_long = (
2679
- # (dataframe['close'] < dataframe['low'].shift(self.sell_shift.value)) &
2680
- (dataframe['close'] < dataframe['ema_l']) &
2681
- (dataframe['volume'] > dataframe['volume_mean_exit'])
2691
+ # (dataframe["close"] < dataframe["low"].shift(self.sell_shift.value)) &
2692
+ (dataframe["close"] < dataframe['ema_l']) &
2693
+ (dataframe["volume"] > dataframe['volume_mean_exit'])
2682
2694
  )
2683
2695
 
2684
2696
  exit_short = (
2685
- # (dataframe['close'] > dataframe['high'].shift(self.sell_shift_short.value)) &
2686
- (dataframe['close'] > dataframe['ema_s']) &
2687
- (dataframe['volume'] > dataframe['volume_mean_exit_s'])
2697
+ # (dataframe["close"] > dataframe["high"].shift(self.sell_shift_short.value)) &
2698
+ (dataframe["close"] > dataframe['ema_s']) &
2699
+ (dataframe["volume"] > dataframe['volume_mean_exit_s'])
2688
2700
  )
2689
2701
 
2690
2702
 
@@ -2726,16 +2738,16 @@ class ScreeningStatistics:
2726
2738
  # dataframe['rsi'] = ta.RSI(dataframe)
2727
2739
 
2728
2740
  # EMA
2729
- dataframe['ema_l'] = pktalib.EMA(dataframe['close'], timeperiod=self.ema_period_l_exit.value)
2730
- dataframe['ema_s'] = pktalib.EMA(dataframe['close'], timeperiod=self.ema_period_s_exit.value)
2741
+ dataframe['ema_l'] = pktalib.EMA(dataframe["close"], timeperiod=self.ema_period_l_exit.value)
2742
+ dataframe['ema_s'] = pktalib.EMA(dataframe["close"], timeperiod=self.ema_period_s_exit.value)
2731
2743
 
2732
2744
 
2733
2745
  # Volume Weighted
2734
- dataframe['volume_mean'] = dataframe['volume'].rolling(self.volume_check.value).mean().shift(1)
2735
- dataframe['volume_mean_exit'] = dataframe['volume'].rolling(self.volume_check_exit.value).mean().shift(1)
2746
+ dataframe['volume_mean'] = dataframe["volume"].rolling(self.volume_check.value).mean().shift(1)
2747
+ dataframe['volume_mean_exit'] = dataframe["volume"].rolling(self.volume_check_exit.value).mean().shift(1)
2736
2748
 
2737
- dataframe['volume_mean_s'] = dataframe['volume'].rolling(self.volume_check_s.value).mean().shift(1)
2738
- dataframe['volume_mean_exit_s'] = dataframe['volume'].rolling(self.volume_check_exit_s.value).mean().shift(1)
2749
+ dataframe['volume_mean_s'] = dataframe["volume"].rolling(self.volume_check_s.value).mean().shift(1)
2750
+ dataframe['volume_mean_exit_s'] = dataframe["volume"].rolling(self.volume_check_exit_s.value).mean().shift(1)
2739
2751
  return dataframe
2740
2752
 
2741
2753
  # Preprocess the acquired data
@@ -2749,36 +2761,36 @@ class ScreeningStatistics:
2749
2761
  # self.default_logger.info(f"Preprocessing data:\n{data.head(1)}\n")
2750
2762
  if daysToLookback is None:
2751
2763
  daysToLookback = self.configManager.daysToLookback
2752
- volatility = df['Close'].rolling(window=20).std()
2764
+ volatility = df["close"].rolling(window=20).std()
2753
2765
  if self.configManager.useEMA:
2754
- sma = pktalib.EMA(data["Close"], timeperiod=50)
2755
- lma = pktalib.EMA(data["Close"], timeperiod=200)
2756
- ssma = pktalib.EMA(data["Close"], timeperiod=9)
2757
- ssma20 = pktalib.EMA(data["Close"], timeperiod=20)
2766
+ sma = pktalib.EMA(data["close"], timeperiod=50)
2767
+ lma = pktalib.EMA(data["close"], timeperiod=200)
2768
+ ssma = pktalib.EMA(data["close"], timeperiod=9)
2769
+ ssma20 = pktalib.EMA(data["close"], timeperiod=20)
2758
2770
  data.insert(len(data.columns), "SMA", sma)
2759
2771
  data.insert(len(data.columns), "LMA", lma)
2760
2772
  data.insert(len(data.columns), "SSMA", ssma)
2761
2773
  data.insert(len(data.columns), "SSMA20", ssma20)
2762
2774
  data.insert(len(data.columns), "Volatility", volatility)
2763
2775
  else:
2764
- sma = pktalib.SMA(data["Close"], timeperiod=50)
2765
- lma = pktalib.SMA(data["Close"], timeperiod=200)
2766
- ssma = pktalib.SMA(data["Close"], timeperiod=9)
2767
- ssma20 = pktalib.SMA(data["Close"], timeperiod=20)
2776
+ sma = pktalib.SMA(data["close"], timeperiod=50)
2777
+ lma = pktalib.SMA(data["close"], timeperiod=200)
2778
+ ssma = pktalib.SMA(data["close"], timeperiod=9)
2779
+ ssma20 = pktalib.SMA(data["close"], timeperiod=20)
2768
2780
  data.insert(len(data.columns), "SMA", sma)
2769
2781
  data.insert(len(data.columns), "LMA", lma)
2770
2782
  data.insert(len(data.columns), "SSMA", ssma)
2771
2783
  data.insert(len(data.columns), "SSMA20", ssma20)
2772
2784
  data.insert(len(data.columns), "Volatility", volatility)
2773
- vol = pktalib.SMA(data["Volume"], timeperiod=20)
2774
- rsi = pktalib.RSI(data["Close"], timeperiod=14)
2785
+ vol = pktalib.SMA(data["volume"], timeperiod=20)
2786
+ rsi = pktalib.RSI(data["close"], timeperiod=14)
2775
2787
  data.insert(len(data.columns), "VolMA", vol)
2776
2788
  data.insert(len(data.columns), "RSI", rsi)
2777
- cci = pktalib.CCI(data["High"], data["Low"], data["Close"], timeperiod=14)
2789
+ cci = pktalib.CCI(data["high"], data["low"], data["close"], timeperiod=14)
2778
2790
  data.insert(len(data.columns), "CCI", cci)
2779
2791
  try:
2780
2792
  fastk, fastd = pktalib.STOCHRSI(
2781
- data["Close"], timeperiod=14, fastk_period=5, fastd_period=3, fastd_matype=0
2793
+ data["close"], timeperiod=14, fastk_period=5, fastd_period=3, fastd_matype=0
2782
2794
  )
2783
2795
  data.insert(len(data.columns), "FASTK", fastk)
2784
2796
  data.insert(len(data.columns), "FASTD", fastd)
@@ -2808,8 +2820,8 @@ class ScreeningStatistics:
2808
2820
  data = data.fillna(0)
2809
2821
  data = data.replace([np.inf, -np.inf], 0)
2810
2822
  data = data[::-1] # Reverse the dataframe so that its the oldest date first
2811
- data["SMA20"] = pktalib.SMA(data["Close"], 20)
2812
- data["SMA20V"] = pktalib.SMA(data["Volume"], 20)
2823
+ data["SMA20"] = pktalib.SMA(data["close"], 20)
2824
+ data["SMA20V"] = pktalib.SMA(data["volume"], 20)
2813
2825
  data = data[
2814
2826
  ::-1
2815
2827
  ] # Reverse the dataframe so that it's the most recent date first
@@ -2817,13 +2829,13 @@ class ScreeningStatistics:
2817
2829
  if len(recent) < 3:
2818
2830
  return False
2819
2831
  # Price at least 1% higher than previous close
2820
- cond1 = recent["Close"].iloc[0] > 1.01*recent["Close"].iloc[1]
2832
+ cond1 = recent["close"].iloc[0] > 1.01*recent["close"].iloc[1]
2821
2833
  # Volume at least 5% higher than previous volume
2822
- cond6 = recent["Volume"].iloc[0] > 1.05*recent["Volume"].iloc[1]
2823
- cond2 = cond1 and cond6 and (recent["Close"].iloc[0] > recent["SMA20"].iloc[0])
2824
- cond3 = cond2 and (recent["Close"].iloc[1] > recent["High"].iloc[2])
2825
- cond4 = cond3 and (recent["Volume"].iloc[0] > 1.05*recent["SMA20V"].iloc[0])
2826
- cond5 = cond4 and (recent["Volume"].iloc[1] > recent["SMA20V"].iloc[0])
2834
+ cond6 = recent["volume"].iloc[0] > 1.05*recent["volume"].iloc[1]
2835
+ cond2 = cond1 and cond6 and (recent["close"].iloc[0] > recent["SMA20"].iloc[0])
2836
+ cond3 = cond2 and (recent["close"].iloc[1] > recent["high"].iloc[2])
2837
+ cond4 = cond3 and (recent["volume"].iloc[0] > 1.05*recent["SMA20V"].iloc[0])
2838
+ cond5 = cond4 and (recent["volume"].iloc[1] > recent["SMA20V"].iloc[0])
2827
2839
  return cond5
2828
2840
 
2829
2841
  def validateBullishForTomorrow(self, df):
@@ -2834,9 +2846,9 @@ class ScreeningStatistics:
2834
2846
  data = data.fillna(0)
2835
2847
  data = data.replace([np.inf, -np.inf], 0)
2836
2848
  data = data[::-1] # Reverse the dataframe so that its the oldest date first
2837
- macdLine = pktalib.MACD(data["Close"], 12, 26, 9)[0].tail(3)
2838
- macdSignal = pktalib.MACD(data["Close"], 12, 26, 9)[1].tail(3)
2839
- macdHist = pktalib.MACD(data["Close"], 12, 26, 9)[2].tail(3)
2849
+ macdLine = pktalib.MACD(data["close"], 12, 26, 9)[0].tail(3)
2850
+ macdSignal = pktalib.MACD(data["close"], 12, 26, 9)[1].tail(3)
2851
+ macdHist = pktalib.MACD(data["close"], 12, 26, 9)[2].tail(3)
2840
2852
 
2841
2853
  return (
2842
2854
  (macdHist.iloc[:1].iloc[0] < macdHist.iloc[:2].iloc[1])
@@ -2914,21 +2926,21 @@ class ScreeningStatistics:
2914
2926
  while recentCurrentDay <= maxRecentDays:
2915
2927
  # 8 ema>21 ema > 55 ema >200 sma each OF THE ema AND THE 200 sma SEPARATED BY LESS THAN 1%(ideally 0.1% TO 0.5%) DURING CONFLUENCE
2916
2928
  if len(emas) >= 1:
2917
- ema_8 = pktalib.EMA(reversedData["Close"],int(emas[0])).tail(recentCurrentDay).head(1).iloc[0]
2918
- ema_8_prev = pktalib.EMA(reversedData["Close"],int(emas[0])).tail(recentCurrentDay+1).head(1).iloc[0]
2929
+ ema_8 = pktalib.EMA(reversedData["close"],int(emas[0])).tail(recentCurrentDay).head(1).iloc[0]
2930
+ ema_8_prev = pktalib.EMA(reversedData["close"],int(emas[0])).tail(recentCurrentDay+1).head(1).iloc[0]
2919
2931
  if len(emas) >= 2:
2920
- ema_21 = pktalib.EMA(reversedData["Close"],int(emas[1])).tail(recentCurrentDay).head(1).iloc[0]
2921
- ema_21_prev = pktalib.EMA(reversedData["Close"],int(emas[1])).tail(recentCurrentDay+1).head(1).iloc[0]
2932
+ ema_21 = pktalib.EMA(reversedData["close"],int(emas[1])).tail(recentCurrentDay).head(1).iloc[0]
2933
+ ema_21_prev = pktalib.EMA(reversedData["close"],int(emas[1])).tail(recentCurrentDay+1).head(1).iloc[0]
2922
2934
  if len(emas) >= 3:
2923
- ema_55 = pktalib.EMA(reversedData["Close"],int(emas[2])).tail(recentCurrentDay).head(1).iloc[0]
2924
- ema_55_prev = pktalib.EMA(reversedData["Close"],int(emas[2])).tail(recentCurrentDay+1).head(1).iloc[0]
2935
+ ema_55 = pktalib.EMA(reversedData["close"],int(emas[2])).tail(recentCurrentDay).head(1).iloc[0]
2936
+ ema_55_prev = pktalib.EMA(reversedData["close"],int(emas[2])).tail(recentCurrentDay+1).head(1).iloc[0]
2925
2937
 
2926
2938
  ema8CrossedEMA21 = (ema_8 >= ema_21 and ema_8_prev <= ema_21_prev) or ema8CrossedEMA21
2927
2939
  ema8CrossedEMA55 = (ema_8 >= ema_55 and ema_8_prev <= ema_55_prev) or ema8CrossedEMA55
2928
2940
  ema21CrossedEMA55 = (ema_21 >= ema_55 and ema_21_prev <= ema_55_prev) or ema21CrossedEMA55
2929
2941
 
2930
- sma_200 = pktalib.SMA(reversedData["Close"],200).tail(recentCurrentDay).head(1).iloc[0]
2931
- # ema9 = pktalib.EMA(reversedData["Close"],9).tail(recentCurrentDay).head(1).iloc[0]
2942
+ sma_200 = pktalib.SMA(reversedData["close"],200).tail(recentCurrentDay).head(1).iloc[0]
2943
+ # ema9 = pktalib.EMA(reversedData["close"],9).tail(recentCurrentDay).head(1).iloc[0]
2932
2944
  # smaRange = sma_200 * percentage
2933
2945
  superConfluenceEnforce200SMA = self.configManager.superConfluenceEnforce200SMA
2934
2946
  # ema_min = min(ema_8, ema_21, ema_55)
@@ -2991,10 +3003,10 @@ class ScreeningStatistics:
2991
3003
  key4 = "50DMA"
2992
3004
  is50DMAUpTrend = (recent[key1].iloc[0] > recent[key2].iloc[1])
2993
3005
  is50DMADownTrend = (recent[key1].iloc[0] < recent[key1].iloc[1])
2994
- is50DMA = (recent[key1].iloc[0] <= recent["Close"].iloc[0])
2995
- is200DMA = (recent[key2].iloc[0] <= recent["Close"].iloc[0])
3006
+ is50DMA = (recent[key1].iloc[0] <= recent["close"].iloc[0])
3007
+ is200DMA = (recent[key2].iloc[0] <= recent["close"].iloc[0])
2996
3008
  difference = round((recent[key1].iloc[0] - recent[key2].iloc[0])
2997
- / recent["Close"].iloc[0]
3009
+ / recent["close"].iloc[0]
2998
3010
  * 100,
2999
3011
  2,
3000
3012
  )
@@ -3044,11 +3056,11 @@ class ScreeningStatistics:
3044
3056
  return False
3045
3057
  data = df.copy()
3046
3058
  reversedData = data[::-1] # Reverse the dataframe
3047
- recentClose = reversedData["Close"].tail(1).head(1).iloc[0]
3048
- yesterdayClose = reversedData["Close"].tail(2).head(1).iloc[0]
3049
- recentOpen = reversedData["Open"].tail(1).head(1).iloc[0]
3050
- yesterdayOpen = reversedData["Open"].tail(2).head(1).iloc[0]
3051
- recentVol = reversedData["Volume"].tail(1).head(1).iloc[0]
3059
+ recentClose = reversedData["close"].tail(1).head(1).iloc[0]
3060
+ yesterdayClose = reversedData["close"].tail(2).head(1).iloc[0]
3061
+ recentOpen = reversedData["open"].tail(1).head(1).iloc[0]
3062
+ yesterdayOpen = reversedData["open"].tail(2).head(1).iloc[0]
3063
+ recentVol = reversedData["volume"].tail(1).head(1).iloc[0]
3052
3064
  # Daily open > 1 day ago open &
3053
3065
  # Daily Close > 1 day ago close &
3054
3066
  # Volume > 1000000
@@ -3070,7 +3082,7 @@ class ScreeningStatistics:
3070
3082
  lma_200 = reversedData["LMA"]
3071
3083
  sma_50 = reversedData["SMA"]
3072
3084
  full52Week = reversedData.tail(50 * one_week)
3073
- full52WeekLow = full52Week["Low"].min()
3085
+ full52WeekLow = full52Week["low"].min()
3074
3086
  #200 MA is rising for at least 3 months
3075
3087
  today = 1
3076
3088
  while today <= one_week * 12: # last 3 months
@@ -3081,14 +3093,14 @@ class ScreeningStatistics:
3081
3093
  if sma_50.tail(1).head(1).iloc[0] <= lma_200.tail(1).head(1).iloc[0]:
3082
3094
  return False
3083
3095
  # Current price is above 20Osma and preferably above 50 to 100
3084
- recentClose = reversedData["Close"].tail(1).head(1).iloc[0]
3096
+ recentClose = reversedData["close"].tail(1).head(1).iloc[0]
3085
3097
  if recentClose < lma_200.tail(1).head(1).iloc[0] or recentClose < 50 or recentClose > 100:
3086
3098
  return False
3087
3099
  # Current price is at least above 100 % from 52week low
3088
3100
  if recentClose <= 2*full52WeekLow:
3089
3101
  return False
3090
3102
  # The stock should have made a 52 week high at least once every 4 to 6 month
3091
- highAsc = reversedData.sort_values(by=["High"], ascending=True)
3103
+ highAsc = reversedData.sort_values(by=["high"], ascending=True)
3092
3104
  highs = highAsc.tail(13)
3093
3105
  dateDiffs = highs.index.to_series().diff().dt.days
3094
3106
  index = 0
@@ -3107,29 +3119,29 @@ class ScreeningStatistics:
3107
3119
  return False
3108
3120
  data = full_df.copy()
3109
3121
  reversedData = data[::-1] # Reverse the dataframe
3110
- recentClose = reversedData["Close"].tail(1).head(1).iloc[0]
3111
- prevClose = reversedData["Close"].tail(2).head(1).iloc[0]
3122
+ recentClose = reversedData["close"].tail(1).head(1).iloc[0]
3123
+ prevClose = reversedData["close"].tail(2).head(1).iloc[0]
3112
3124
  tradingAbove2Percent = (recentClose-prevClose)*100/prevClose > 2
3113
3125
  if tradingAbove2Percent:
3114
- prevHigh = reversedData["High"].tail(2).head(1).iloc[0]
3126
+ prevHigh = reversedData["high"].tail(2).head(1).iloc[0]
3115
3127
  tradingAbovePrevHighAnd50MA = (recentClose > prevHigh) and (recentClose > reversedData["SMA"].tail(1).head(1).iloc[0])
3116
3128
  # return tradingAbovePrevHighAnd50MA
3117
3129
  # resampling 1-min data to 5 min for 200MA requires at least 5d data to
3118
3130
  # be downloaded which is pretty huge (~460MB). So skipping this for now.
3119
3131
  if tradingAbovePrevHighAnd50MA:
3120
3132
  ohlc_dict = {
3121
- 'Open':'first',
3122
- 'High':'max',
3123
- 'Low':'min',
3124
- 'Close':'last',
3133
+ "open":'first',
3134
+ "high":'max',
3135
+ "low":'min',
3136
+ "close":'last',
3125
3137
  'Adj Close': 'last',
3126
- 'Volume':'sum'
3138
+ "volume":'sum'
3127
3139
  }
3128
3140
  data_5min = df_5min.copy()
3129
3141
  reversedData_5min = data_5min[::-1] # Reverse the dataframe
3130
3142
  reversedData_5min = reversedData_5min.resample(f'5T', offset='15min').agg(ohlc_dict)
3131
3143
  reversedData_5min.dropna(inplace=True)
3132
- sma200_5min = pktalib.SMA(reversedData_5min["Close"],timeperiod=200)
3144
+ sma200_5min = pktalib.SMA(reversedData_5min["close"],timeperiod=200)
3133
3145
  return recentClose > sma200_5min.tail(1).head(1).iloc[0]
3134
3146
  return False
3135
3147
 
@@ -3141,8 +3153,8 @@ class ScreeningStatistics:
3141
3153
  data = df.copy()
3142
3154
  data = data.fillna(0)
3143
3155
  data = data.replace([np.inf, -np.inf], 0)
3144
- hc = data.describe()["Close"]["max"]
3145
- lc = data.describe()["Close"]["min"]
3156
+ hc = data.describe()["close"]["max"]
3157
+ lc = data.describe()["close"]["min"]
3146
3158
  if (hc - lc) <= (hc * percentage / 100) and (hc - lc != 0):
3147
3159
  screenDict["Consol."] = (
3148
3160
  colorText.GREEN
@@ -3249,19 +3261,19 @@ class ScreeningStatistics:
3249
3261
  if len(day1) < 1 or len(day2) < 1 or len(day3) < 1:
3250
3262
  return False
3251
3263
  higherHighs = (
3252
- (day0["High"].iloc[0] > day1["High"].iloc[0])
3253
- and (day1["High"].iloc[0] > day2["High"].iloc[0])
3254
- and (day2["High"].iloc[0] > day3["High"].iloc[0])
3264
+ (day0["high"].iloc[0] > day1["high"].iloc[0])
3265
+ and (day1["high"].iloc[0] > day2["high"].iloc[0])
3266
+ and (day2["high"].iloc[0] > day3["high"].iloc[0])
3255
3267
  )
3256
3268
  higherLows = (
3257
- (day0["Low"].iloc[0] > day1["Low"].iloc[0])
3258
- and (day1["Low"].iloc[0] > day2["Low"].iloc[0])
3259
- and (day2["Low"].iloc[0] > day3["Low"].iloc[0])
3269
+ (day0["low"].iloc[0] > day1["low"].iloc[0])
3270
+ and (day1["low"].iloc[0] > day2["low"].iloc[0])
3271
+ and (day2["low"].iloc[0] > day3["low"].iloc[0])
3260
3272
  )
3261
3273
  higherClose = (
3262
- (day0["Close"].iloc[0] > day1["Close"].iloc[0])
3263
- and (day1["Close"].iloc[0] > day2["Close"].iloc[0])
3264
- and (day2["Close"].iloc[0] > day3["Close"].iloc[0])
3274
+ (day0["close"].iloc[0] > day1["close"].iloc[0])
3275
+ and (day1["close"].iloc[0] > day2["close"].iloc[0])
3276
+ and (day2["close"].iloc[0] > day3["close"].iloc[0])
3265
3277
  )
3266
3278
  # higherRSI = (day0["RSI"].iloc[0] > day1["RSI"].iloc[0]) and \
3267
3279
  # (day1["RSI"].iloc[0] > day2["RSI"].iloc[0]) and \
@@ -3269,11 +3281,11 @@ class ScreeningStatistics:
3269
3281
  # day3["RSI"].iloc[0] >= 50 and day0["RSI"].iloc[0] >= 65
3270
3282
  reversedData = data[::-1].copy()
3271
3283
  reversedData["SUPERT"] = pktalib.supertrend(reversedData, 7, 3)["SUPERT_7_3.0"]
3272
- reversedData["EMA8"] = pktalib.EMA(reversedData["Close"], timeperiod=9)
3284
+ reversedData["EMA8"] = pktalib.EMA(reversedData["close"], timeperiod=9)
3273
3285
  higherClose = (
3274
3286
  higherClose
3275
- and day0["Close"].iloc[0] > reversedData.tail(1)["SUPERT"].iloc[0]
3276
- and day0["Close"].iloc[0] > reversedData.tail(1)["EMA8"].iloc[0]
3287
+ and day0["close"].iloc[0] > reversedData.tail(1)["SUPERT"].iloc[0]
3288
+ and day0["close"].iloc[0] > reversedData.tail(1)["EMA8"].iloc[0]
3277
3289
  )
3278
3290
  return higherHighs and higherLows and higherClose
3279
3291
 
@@ -3298,10 +3310,10 @@ class ScreeningStatistics:
3298
3310
  data = orgData.head(i)
3299
3311
  refCandle = data.tail(1)
3300
3312
  if (
3301
- (len(data.High[data.High > refCandle.High.item()]) == 0)
3302
- and (len(data.Low[data.Low < refCandle.Low.item()]) == 0)
3303
- and (len(data.Open[data.Open > refCandle.High.item()]) == 0)
3304
- and (len(data.Close[data.Close < refCandle.Low.item()]) == 0)
3313
+ (len(data.high[data.high > refCandle.high.item()]) == 0)
3314
+ and (len(data.low[data.low < refCandle.low.item()]) == 0)
3315
+ and (len(data.open[data.open > refCandle.high.item()]) == 0)
3316
+ and (len(data.close[data.close < refCandle.low.item()]) == 0)
3305
3317
  ):
3306
3318
  screenDict["Pattern"] = (
3307
3319
  saved[0]
@@ -3320,10 +3332,10 @@ class ScreeningStatistics:
3320
3332
  data = orgData.head(i)
3321
3333
  refCandle = data.tail(1)
3322
3334
  if (
3323
- (len(data.High[data.High > refCandle.High.item()]) == 0)
3324
- and (len(data.Low[data.Low < refCandle.Low.item()]) == 0)
3325
- and (len(data.Open[data.Open > refCandle.High.item()]) == 0)
3326
- and (len(data.Close[data.Close < refCandle.Low.item()]) == 0)
3335
+ (len(data.high[data.high > refCandle.high.item()]) == 0)
3336
+ and (len(data.low[data.low < refCandle.low.item()]) == 0)
3337
+ and (len(data.open[data.open > refCandle.high.item()]) == 0)
3338
+ and (len(data.close[data.close < refCandle.low.item()]) == 0)
3327
3339
  ):
3328
3340
  screenDict["Pattern"] = (
3329
3341
  saved[0]
@@ -3342,9 +3354,9 @@ class ScreeningStatistics:
3342
3354
  if df is None or len(df) == 0:
3343
3355
  return False
3344
3356
  data = df.copy()
3345
- listingPrice = data[::-1].head(1)["Open"].iloc[0]
3346
- currentPrice = data.head(1)["Close"].iloc[0]
3347
- ATH = data.describe()["High"]["max"]
3357
+ listingPrice = data[::-1].head(1)["open"].iloc[0]
3358
+ currentPrice = data.head(1)["close"].iloc[0]
3359
+ ATH = data.describe()["high"]["max"]
3348
3360
  if ATH > (listingPrice + (listingPrice * percentage)):
3349
3361
  return False
3350
3362
  away = round(((currentPrice - listingPrice) / listingPrice) * 100, 1)
@@ -3384,11 +3396,11 @@ class ScreeningStatistics:
3384
3396
  data = data[::-1] # Reverse the dataframe
3385
3397
  data = data.rename(
3386
3398
  columns={
3387
- "Open": "open",
3388
- "Close": "close",
3389
- "High": "high",
3390
- "Low": "low",
3391
- "Volume": "volume",
3399
+ "open": "open",
3400
+ "close": "close",
3401
+ "high": "high",
3402
+ "low": "low",
3403
+ "volume": "volume",
3392
3404
  }
3393
3405
  )
3394
3406
  try:
@@ -3400,10 +3412,10 @@ class ScreeningStatistics:
3400
3412
  ata.LorentzianClassification.Feature("CCI", 20, 2), # f3
3401
3413
  ata.LorentzianClassification.Feature("ADX", 20, 2), # f4
3402
3414
  ata.LorentzianClassification.Feature("RSI", 9, 2), # f5
3403
- pktalib.MFI(data['high'], data['low'], data['close'], data['volume'], 14) #f6
3415
+ pktalib.MFI(data["high"], data["low"], data["close"], data["volume"], 14) #f6
3404
3416
  ],
3405
3417
  settings=ata.LorentzianClassification.Settings(
3406
- source=data['close'],
3418
+ source=data["close"],
3407
3419
  neighborsCount=8,
3408
3420
  maxBarsBack=2000,
3409
3421
  useDynamicExits=False
@@ -3465,14 +3477,14 @@ class ScreeningStatistics:
3465
3477
  day2 = data[2:]
3466
3478
  day3 = data[3:]
3467
3479
  lowerHighs = (
3468
- (day0["High"].iloc[0] < day1["High"].iloc[0])
3469
- and (day1["High"].iloc[0] < day2["High"].iloc[0])
3470
- and (day2["High"].iloc[0] < day3["High"].iloc[0])
3480
+ (day0["high"].iloc[0] < day1["high"].iloc[0])
3481
+ and (day1["high"].iloc[0] < day2["high"].iloc[0])
3482
+ and (day2["high"].iloc[0] < day3["high"].iloc[0])
3471
3483
  )
3472
3484
  lowerLows = (
3473
- (day0["Low"].iloc[0] < day1["Low"].iloc[0])
3474
- and (day1["Low"].iloc[0] < day2["Low"].iloc[0])
3475
- and (day2["Low"].iloc[0] < day3["Low"].iloc[0])
3485
+ (day0["low"].iloc[0] < day1["low"].iloc[0])
3486
+ and (day1["low"].iloc[0] < day2["low"].iloc[0])
3487
+ and (day2["low"].iloc[0] < day3["low"].iloc[0])
3476
3488
  )
3477
3489
  higherRSI = (
3478
3490
  (day0["RSI"].iloc[0] < day1["RSI"].iloc[0])
@@ -3497,8 +3509,8 @@ class ScreeningStatistics:
3497
3509
  recent = data.head(1)
3498
3510
  if len(recent) < 1:
3499
3511
  return False
3500
- if (recent["Volume"].iloc[0] <= data.describe()["Volume"]["min"]) and recent[
3501
- "Volume"
3512
+ if (recent["volume"].iloc[0] <= data.describe()["volume"]["min"]) and recent[
3513
+ "volume"
3502
3514
  ][0] != np.nan:
3503
3515
  return True
3504
3516
  return False
@@ -3515,7 +3527,7 @@ class ScreeningStatistics:
3515
3527
  data = data.replace([np.inf, -np.inf], 0)
3516
3528
  recent = data.head(1)
3517
3529
 
3518
- pct_change = (data[::-1]["Close"].pct_change() * 100).iloc[-1]
3530
+ pct_change = (data[::-1]["close"].pct_change() * 100).iloc[-1]
3519
3531
  if pct_change == np.inf or pct_change == -np.inf:
3520
3532
  pct_change = 0
3521
3533
  pct_save = "%.1f%%" % pct_change
@@ -3527,11 +3539,11 @@ class ScreeningStatistics:
3527
3539
  pct_change = colorText.WARN + ("%.1f%%" % pct_change) + colorText.END
3528
3540
  saveDict["%Chng"] = pct_save
3529
3541
  screenDict["%Chng"] = pct_change
3530
- ltp = round(recent["Close"].iloc[0], 2)
3542
+ ltp = round(recent["close"].iloc[0], 2)
3531
3543
  verifyStageTwo = True
3532
3544
  if len(data) > 250:
3533
- yearlyLow = data.head(250)["Close"].min()
3534
- yearlyHigh = data.head(250)["Close"].max()
3545
+ yearlyLow = data.head(250)["close"].min()
3546
+ yearlyHigh = data.head(250)["close"].max()
3535
3547
  if ltp < (2 * yearlyLow) and ltp < (0.75 * yearlyHigh):
3536
3548
  verifyStageTwo = False
3537
3549
  screenDict["Stock"] = colorText.FAIL + saveDict["Stock"] + colorText.END
@@ -3578,8 +3590,8 @@ class ScreeningStatistics:
3578
3590
  calc_date = str(previous_recent.iloc[:, 0][0]).split(" ")[0]
3579
3591
  for prd in periods:
3580
3592
  if len(data) >= prd + 1:
3581
- prevLtp = data["Close"].iloc[0]
3582
- ltpTdy = data["Close"].iloc[prd]
3593
+ prevLtp = data["close"].iloc[0]
3594
+ ltpTdy = data["close"].iloc[prd]
3583
3595
  if isinstance(prevLtp,pd.Series):
3584
3596
  prevLtp = prevLtp[0]
3585
3597
  ltpTdy = ltpTdy[0]
@@ -3600,7 +3612,7 @@ class ScreeningStatistics:
3600
3612
  saveDict[f"{prd}-Pd"] = f"{changePercent}%" if not pd.isna(changePercent) else '-'
3601
3613
  screenDict[f"{prd}-Pd"] = ((colorText.GREEN if changePercent >=0 else colorText.FAIL) + f"{changePercent}%" + colorText.END) if not pd.isna(changePercent) else '-'
3602
3614
  if (prd == requestedPeriod):
3603
- maxLTPPotential = max(data["High"].head(prd))
3615
+ maxLTPPotential = max(data["high"].head(prd))
3604
3616
  screenDict[f"MaxLTP"] = (
3605
3617
  (colorText.GREEN if (maxLTPPotential >= prevLtp) else (colorText.FAIL))
3606
3618
  + str("{:.2f}".format(maxLTPPotential))
@@ -3629,7 +3641,7 @@ class ScreeningStatistics:
3629
3641
  data = data.fillna(0)
3630
3642
  data = data.replace([np.inf, -np.inf], 0)
3631
3643
  data = data[::-1] # Reverse the dataframe so that its the oldest date first
3632
- macd = pktalib.MACD(data["Close"], 12, 26, 9)[2].tail(1)
3644
+ macd = pktalib.MACD(data["close"], 12, 26, 9)[2].tail(1)
3633
3645
  return macd.iloc[:1][0] < 0
3634
3646
 
3635
3647
  #@measure_time
@@ -3644,16 +3656,16 @@ class ScreeningStatistics:
3644
3656
  return False
3645
3657
  for row in data.iterrows():
3646
3658
  # All 3 candles should be Green and NOT Circuits
3647
- yc = row[1]["Close"]
3648
- yo = row[1]["Open"]
3659
+ yc = row[1]["close"]
3660
+ yo = row[1]["open"]
3649
3661
  if yc <= yo:
3650
3662
  # self.default_logger.info(
3651
3663
  # f'Stock:{saveDict["Stock"]}, is not a momentum-gainer because yesterday-close ({yc}) <= yesterday-open ({yo})'
3652
3664
  # )
3653
3665
  return False
3654
- openDesc = data.sort_values(by=["Open"], ascending=False)
3655
- closeDesc = data.sort_values(by=["Close"], ascending=False)
3656
- volDesc = data.sort_values(by=["Volume"], ascending=False)
3666
+ openDesc = data.sort_values(by=["open"], ascending=False)
3667
+ closeDesc = data.sort_values(by=["close"], ascending=False)
3668
+ volDesc = data.sort_values(by=["volume"], ascending=False)
3657
3669
  try:
3658
3670
  if (
3659
3671
  data.equals(openDesc)
@@ -3663,10 +3675,10 @@ class ScreeningStatistics:
3663
3675
  # self.default_logger.info(
3664
3676
  # f'Stock:{saveDict["Stock"]}, open,close and volume equal from day before yesterday. A potential momentum-gainer!'
3665
3677
  # )
3666
- to = data["Open"].iloc[0]
3667
- yc = data["Close"].iloc[1]
3668
- yo = data["Open"].iloc[1]
3669
- dyc = data["Close"].iloc[2]
3678
+ to = data["open"].iloc[0]
3679
+ yc = data["close"].iloc[1]
3680
+ yo = data["open"].iloc[1]
3681
+ dyc = data["close"].iloc[2]
3670
3682
  if (to >= yc) and (yo >= dyc):
3671
3683
  # self.default_logger.info(
3672
3684
  # f'Stock:{saveDict["Stock"]}, is a momentum-gainer because today-open ({to}) >= yesterday-close ({yc}) and yesterday-open({yo}) >= day-before-close({dyc})'
@@ -3706,7 +3718,7 @@ class ScreeningStatistics:
3706
3718
  saved = self.findCurrentSavedValue(screenDict,saveDict,"MA-Signal")
3707
3719
  if (
3708
3720
  recent["SMA"].iloc[0] > recent["LMA"].iloc[0]
3709
- and recent["Close"].iloc[0] > recent["SMA"].iloc[0]
3721
+ and recent["close"].iloc[0] > recent["SMA"].iloc[0]
3710
3722
  ):
3711
3723
  screenDict["MA-Signal"] = (
3712
3724
  saved[0] + colorText.GREEN + "Bullish" + colorText.END
@@ -3730,17 +3742,17 @@ class ScreeningStatistics:
3730
3742
  )
3731
3743
  saveDict["MA-Signal"] = saved[1] + "Neutral"
3732
3744
  reversedData = data[::-1] # Reverse the dataframe
3733
- ema_20 = pktalib.EMA(reversedData["Close"],20).tail(1).iloc[0]
3734
- vwap = pktalib.VWAP(reversedData["High"],reversedData["Low"],reversedData["Close"],reversedData["Volume"]).tail(1).iloc[0]
3745
+ ema_20 = pktalib.EMA(reversedData["close"],20).tail(1).iloc[0]
3746
+ vwap = pktalib.VWAP(reversedData["high"],reversedData["low"],reversedData["close"],reversedData["volume"]).tail(1).iloc[0]
3735
3747
  smaDev = data["SMA"].iloc[0] * maRange / 100
3736
3748
  lmaDev = data["LMA"].iloc[0] * maRange / 100
3737
3749
  emaDev = ema_20 * maRange / 100
3738
3750
  vwapDev = vwap * maRange / 100
3739
3751
  open, high, low, close, sma, lma = (
3740
- data["Open"].iloc[0],
3741
- data["High"].iloc[0],
3742
- data["Low"].iloc[0],
3743
- data["Close"].iloc[0],
3752
+ data["open"].iloc[0],
3753
+ data["high"].iloc[0],
3754
+ data["low"].iloc[0],
3755
+ data["close"].iloc[0],
3744
3756
  data["SMA"].iloc[0],
3745
3757
  data["LMA"].iloc[0],
3746
3758
  )
@@ -3810,7 +3822,7 @@ class ScreeningStatistics:
3810
3822
  if PKDateUtilities.isTradingTime():
3811
3823
  rangeData = data.head(nr + 1)[1:]
3812
3824
  now_candle = data.head(1)
3813
- rangeData["Range"] = abs(rangeData["Close"] - rangeData["Open"])
3825
+ rangeData["Range"] = abs(rangeData["close"] - rangeData["open"])
3814
3826
  recent = rangeData.head(1)
3815
3827
  if (
3816
3828
  len(recent) == 1
@@ -3818,7 +3830,7 @@ class ScreeningStatistics:
3818
3830
  ):
3819
3831
  if (
3820
3832
  self.getCandleType(recent)
3821
- and now_candle["Close"].iloc[0] >= recent["Close"].iloc[0]
3833
+ and now_candle["close"].iloc[0] >= recent["close"].iloc[0]
3822
3834
  ):
3823
3835
  screenDict["Pattern"] = (
3824
3836
  saved[0] + colorText.GREEN + f"Buy-NR{nr}" + colorText.END
@@ -3827,7 +3839,7 @@ class ScreeningStatistics:
3827
3839
  return True
3828
3840
  elif (
3829
3841
  not self.getCandleType(recent)
3830
- and now_candle["Close"].iloc[0] <= recent["Close"].iloc[0]
3842
+ and now_candle["close"].iloc[0] <= recent["close"].iloc[0]
3831
3843
  ):
3832
3844
  screenDict["Pattern"] = (
3833
3845
  saved[0] + colorText.FAIL + f"Sell-NR{nr}" + colorText.END
@@ -3837,7 +3849,7 @@ class ScreeningStatistics:
3837
3849
  return False
3838
3850
  else:
3839
3851
  rangeData = data.head(nr)
3840
- rangeData.loc[:,'Range'] = abs(rangeData["Close"] - rangeData["Open"])
3852
+ rangeData.loc[:,'Range'] = abs(rangeData["close"] - rangeData["open"])
3841
3853
  recent = rangeData.head(1)
3842
3854
  if recent["Range"].iloc[0] == rangeData.describe()["Range"]["min"]:
3843
3855
  screenDict["Pattern"] = (
@@ -3859,7 +3871,7 @@ class ScreeningStatistics:
3859
3871
  if len(recent) < 1:
3860
3872
  return False
3861
3873
  if len(data) < daysToLookback and (
3862
- recent["Close"].iloc[0] != np.nan and recent["Close"].iloc[0] > 0
3874
+ recent["close"].iloc[0] != np.nan and recent["close"].iloc[0] > 0
3863
3875
  ):
3864
3876
  return True
3865
3877
  return False
@@ -3873,7 +3885,7 @@ class ScreeningStatistics:
3873
3885
  for ma in mas:
3874
3886
  if len(reversedData) <= int(ma):
3875
3887
  continue
3876
- hasCrossed, percentageDiff = self.findPriceActionCross(df=reversedData,ma=ma,daysToConsider=1,baseMAOrPrice=reversedData["Close"].tail(2),isEMA=isEMA,maDirectionFromBelow=maDirectionFromBelow)
3888
+ hasCrossed, percentageDiff = self.findPriceActionCross(df=reversedData,ma=ma,daysToConsider=1,baseMAOrPrice=reversedData["close"].tail(2),isEMA=isEMA,maDirectionFromBelow=maDirectionFromBelow)
3877
3889
  if hasCrossed:
3878
3890
  if not hasAtleastOneMACross:
3879
3891
  hasAtleastOneMACross = True
@@ -3891,17 +3903,17 @@ class ScreeningStatistics:
3891
3903
  pp_map = {"1":"PP","2":"S1","3":"S2","4":"S3","5":"R1","6":"R2","7":"R3"}
3892
3904
  if pivotPoint is not None and pivotPoint != "0" and str(pivotPoint).isnumeric():
3893
3905
  ppToCheck = pp_map[str(pivotPoint)]
3894
- ppsr_df = pktalib.get_ppsr_df(data["High"],data["Low"],data["Close"],ppToCheck)
3906
+ ppsr_df = pktalib.get_ppsr_df(data["high"],data["low"],data["close"],ppToCheck)
3895
3907
  if ppsr_df is None:
3896
3908
  return False
3897
3909
  if crossDirectionFromBelow:
3898
- hasPriceCross = (ppsr_df["Close"].iloc[0] > ppsr_df[ppToCheck].iloc[0] and
3899
- ppsr_df["Close"].iloc[1] <= ppsr_df[ppToCheck].iloc[1])
3910
+ hasPriceCross = (ppsr_df["close"].iloc[0] > ppsr_df[ppToCheck].iloc[0] and
3911
+ ppsr_df["close"].iloc[1] <= ppsr_df[ppToCheck].iloc[1])
3900
3912
  else:
3901
- hasPriceCross = (ppsr_df["Close"].iloc[0] < ppsr_df[ppToCheck].iloc[0] and
3902
- ppsr_df["Close"].iloc[1] >= ppsr_df[ppToCheck].iloc[1])
3913
+ hasPriceCross = (ppsr_df["close"].iloc[0] < ppsr_df[ppToCheck].iloc[0] and
3914
+ ppsr_df["close"].iloc[1] >= ppsr_df[ppToCheck].iloc[1])
3903
3915
  if hasPriceCross:
3904
- percentageDiff = round(100*(ppsr_df["Close"].iloc[0]-ppsr_df[ppToCheck].iloc[0])/ppsr_df[ppToCheck].iloc[0],1)
3916
+ percentageDiff = round(100*(ppsr_df["close"].iloc[0]-ppsr_df[ppToCheck].iloc[0])/ppsr_df[ppToCheck].iloc[0],1)
3905
3917
  saved = self.findCurrentSavedValue(screenDict,saveDict,"MA-Signal")
3906
3918
  maText = f"Cross-{'FromBelow' if crossDirectionFromBelow else 'FromAbove'}({ppToCheck}:{ppsr_df[ppToCheck].iloc[0]})"
3907
3919
  saveDict["MA-Signal"] = saved[1] + maText + f"({percentageDiff}%)"
@@ -3918,10 +3930,10 @@ class ScreeningStatistics:
3918
3930
  data = data.head(4)
3919
3931
  if len(data) < 4:
3920
3932
  return False
3921
- day0 = data.iloc[0]["Close"].item()
3922
- dayMinus1 = data.iloc[1]["Close"].item()
3923
- dayMinus2 = data.iloc[2]["Close"].item()
3924
- dayMinus3 = data.iloc[3]["Close"].item()
3933
+ day0 = data.iloc[0]["close"].item()
3934
+ dayMinus1 = data.iloc[1]["close"].item()
3935
+ dayMinus2 = data.iloc[2]["close"].item()
3936
+ dayMinus3 = data.iloc[3]["close"].item()
3925
3937
  percent3 = round((dayMinus2 - dayMinus3) * 100 / dayMinus3, 2)
3926
3938
  percent2 = round((dayMinus1 - dayMinus2) * 100 / dayMinus2, 2)
3927
3939
  percent1 = round((day0 - dayMinus1) * 100 / dayMinus1, 2)
@@ -3974,11 +3986,11 @@ class ScreeningStatistics:
3974
3986
  try:
3975
3987
  df_ichi = df_new.rename(
3976
3988
  columns={
3977
- "Open": "open",
3978
- "High": "high",
3979
- "Low": "low",
3980
- "Close": "close",
3981
- "Volume": "volume",
3989
+ "open": "open",
3990
+ "high": "high",
3991
+ "low": "low",
3992
+ "close": "close",
3993
+ "volume": "volume",
3982
3994
  }
3983
3995
  )
3984
3996
  ichi = pktalib.ichimoku(df_ichi, 9, 26, 52, 26)
@@ -4000,12 +4012,12 @@ class ScreeningStatistics:
4000
4012
  if df_new["cloud_green"].iloc[0]:
4001
4013
  aboveCloudTop = (
4002
4014
  df_new["IKS_26"].iloc[0] > df_new["ISA_9"].iloc[0]
4003
- and recent["Close"].iloc[0] > df_new["ISA_9"].iloc[0]
4015
+ and recent["close"].iloc[0] > df_new["ISA_9"].iloc[0]
4004
4016
  )
4005
4017
  elif df_new["cloud_red"].iloc[0]:
4006
4018
  aboveCloudTop = (
4007
4019
  df_new["IKS_26"].iloc[0] > df_new["ISB_26"].iloc[0]
4008
- and recent["Close"].iloc[0] > df_new["ISB_26"].iloc[0]
4020
+ and recent["close"].iloc[0] > df_new["ISB_26"].iloc[0]
4009
4021
  )
4010
4022
 
4011
4023
  # Latest Ichimoku baseline is < latest Ichimoku conversion line
@@ -4020,8 +4032,8 @@ class ScreeningStatistics:
4020
4032
  # close > 50 period SMA/EMA and 200 period SMA/EMA
4021
4033
  if (
4022
4034
  recent["SSMA"].iloc[0] > recent["SMA"].iloc[0]
4023
- and recent["Close"].iloc[0] > recent["SSMA"].iloc[0]
4024
- and recent["Close"].iloc[0] > recent["LMA"].iloc[0]
4035
+ and recent["close"].iloc[0] > recent["SSMA"].iloc[0]
4036
+ and recent["close"].iloc[0] > recent["LMA"].iloc[0]
4025
4037
  ):
4026
4038
  saved = self.findCurrentSavedValue(screenDict,saveDict,"MA-Signal")
4027
4039
  screenDict["MA-Signal"] = (
@@ -4041,22 +4053,22 @@ class ScreeningStatistics:
4041
4053
  try:
4042
4054
  if self.configManager.enableAdditionalVCPEMAFilters:
4043
4055
  reversedData = data[::-1]
4044
- ema = pktalib.EMA(reversedData["Close"], timeperiod=50)
4045
- sema20 = pktalib.EMA(reversedData["Close"], timeperiod=20)
4046
- if not (data["Close"].iloc[0] >= ema.tail(1).iloc[0] and data["Close"].iloc[0] >= sema20.tail(1).iloc[0]):
4056
+ ema = pktalib.EMA(reversedData["close"], timeperiod=50)
4057
+ sema20 = pktalib.EMA(reversedData["close"], timeperiod=20)
4058
+ if not (data["close"].iloc[0] >= ema.tail(1).iloc[0] and data["close"].iloc[0] >= sema20.tail(1).iloc[0]):
4047
4059
  return False
4048
4060
  percentageFromTop /= 100
4049
4061
  data.reset_index(inplace=True)
4050
4062
  data.rename(columns={"index": "Date"}, inplace=True)
4051
- data["tops"] = (data["High"].iloc[list(pktalib.argrelextrema(np.array(data["High"]), np.greater_equal, order=window)[0])].head(4))
4052
- data["bots"] = (data["Low"].iloc[list(pktalib.argrelextrema(np.array(data["Low"]), np.less_equal, order=window)[0])].head(4))
4063
+ data["tops"] = (data["high"].iloc[list(pktalib.argrelextrema(np.array(data["high"]), np.greater_equal, order=window)[0])].head(4))
4064
+ data["bots"] = (data["low"].iloc[list(pktalib.argrelextrema(np.array(data["low"]), np.less_equal, order=window)[0])].head(4))
4053
4065
  data = data.fillna(0)
4054
4066
  data = data.replace([np.inf, -np.inf], 0)
4055
4067
  tops = data[data.tops > 0]
4056
4068
  # bots = data[data.bots > 0]
4057
- highestTop = round(tops.describe()["High"]["max"], 1)
4058
- allTimeHigh = max(data["High"])
4059
- withinATHRange = data["Close"].iloc[0] >= (allTimeHigh-allTimeHigh * float(self.configManager.vcpRangePercentageFromTop)/100)
4069
+ highestTop = round(tops.describe()["high"]["max"], 1)
4070
+ allTimeHigh = max(data["high"])
4071
+ withinATHRange = data["close"].iloc[0] >= (allTimeHigh-allTimeHigh * float(self.configManager.vcpRangePercentageFromTop)/100)
4060
4072
  if not withinATHRange and self.configManager.enableAdditionalVCPFilters:
4061
4073
  # Last close is not within all time high range
4062
4074
  return False
@@ -4071,14 +4083,14 @@ class ScreeningStatistics:
4071
4083
  lowPoints.append(
4072
4084
  data[
4073
4085
  (data.Date >= startDate) & (data.Date <= endDate)
4074
- ].describe()["Low"]["min"]
4086
+ ].describe()["low"]["min"]
4075
4087
  )
4076
4088
  lowPointsOrg = lowPoints
4077
4089
  lowPoints.sort(reverse=True)
4078
4090
  lowPointsSorted = lowPoints
4079
4091
  if data.empty or len(lowPoints) < 1:
4080
4092
  return False
4081
- ltp = data.head(1)["Close"].iloc[0]
4093
+ ltp = data.head(1)["close"].iloc[0]
4082
4094
  if (
4083
4095
  lowPointsOrg == lowPointsSorted
4084
4096
  and ltp < highestTop
@@ -4112,41 +4124,41 @@ class ScreeningStatistics:
4112
4124
  return False
4113
4125
  data = df.copy()
4114
4126
  ohlc_dict = {
4115
- 'Open':'first',
4116
- 'High':'max',
4117
- 'Low':'min',
4118
- 'Close':'last',
4119
- 'Volume':'sum'
4127
+ "open":'first',
4128
+ "high":'max',
4129
+ "low":'min',
4130
+ "close":'last',
4131
+ "volume":'sum'
4120
4132
  }
4121
4133
  # final_df = df.resample('W-FRI', closed='left').agg(ohlc_dict).shift('1d')
4122
4134
  weeklyData = data.resample('W').agg(ohlc_dict)
4123
4135
  reversedData = data[::-1] # Reverse the dataframe
4124
- recent_close = data["Close"].head(1).iloc[0]
4125
- w_ema_13 = pktalib.EMA(weeklyData["Close"],timeperiod=13).tail(1).iloc[0]
4126
- w_ema_26 = pktalib.EMA(weeklyData["Close"],timeperiod=26).tail(1).iloc[0]
4127
- w_sma_50 = pktalib.SMA(weeklyData["Close"],timeperiod=50).tail(1).iloc[0]
4128
- w_sma_40 = pktalib.SMA(weeklyData["Close"],timeperiod=40).tail(1).iloc[0]
4129
- w_sma_40_5w_ago = pktalib.SMA(weeklyData.head(len(weeklyData)-5)["Close"],timeperiod=40).tail(1).iloc[0]
4130
- w_min_50 = min(1.3*weeklyData.tail(50)["Low"])
4131
- w_max_50 = max(0.75*weeklyData.tail(50)["High"])
4132
- w_ema_26_20w_ago = pktalib.EMA(weeklyData.head(len(weeklyData)-20)["Close"],timeperiod=26).tail(1).iloc[0]
4133
- recent_ema_13_20d_ago = pktalib.EMA(reversedData.head(len(reversedData)-20)["Close"],timeperiod=13).tail(1).iloc[0]
4134
- w_sma_40_5w_ago = pktalib.SMA(weeklyData.head(len(weeklyData)-5)["Close"],timeperiod=40).tail(1).iloc[0]
4135
- w_sma_40_10w_ago = pktalib.SMA(weeklyData.head(len(weeklyData)-10)["Close"],timeperiod=40).tail(1).iloc[0]
4136
- recent_sma_50 = pktalib.SMA(reversedData["Close"],timeperiod=50).tail(1).iloc[0]
4137
- w_wma_8 = pktalib.WMA(weeklyData["Close"],timeperiod=8).tail(1).iloc[0]
4138
- w_sma_8 = pktalib.SMA(weeklyData["Close"],timeperiod=8).tail(1).iloc[0]
4136
+ recent_close = data["close"].head(1).iloc[0]
4137
+ w_ema_13 = pktalib.EMA(weeklyData["close"],timeperiod=13).tail(1).iloc[0]
4138
+ w_ema_26 = pktalib.EMA(weeklyData["close"],timeperiod=26).tail(1).iloc[0]
4139
+ w_sma_50 = pktalib.SMA(weeklyData["close"],timeperiod=50).tail(1).iloc[0]
4140
+ w_sma_40 = pktalib.SMA(weeklyData["close"],timeperiod=40).tail(1).iloc[0]
4141
+ w_sma_40_5w_ago = pktalib.SMA(weeklyData.head(len(weeklyData)-5)["close"],timeperiod=40).tail(1).iloc[0]
4142
+ w_min_50 = min(1.3*weeklyData.tail(50)["low"])
4143
+ w_max_50 = max(0.75*weeklyData.tail(50)["high"])
4144
+ w_ema_26_20w_ago = pktalib.EMA(weeklyData.head(len(weeklyData)-20)["close"],timeperiod=26).tail(1).iloc[0]
4145
+ recent_ema_13_20d_ago = pktalib.EMA(reversedData.head(len(reversedData)-20)["close"],timeperiod=13).tail(1).iloc[0]
4146
+ w_sma_40_5w_ago = pktalib.SMA(weeklyData.head(len(weeklyData)-5)["close"],timeperiod=40).tail(1).iloc[0]
4147
+ w_sma_40_10w_ago = pktalib.SMA(weeklyData.head(len(weeklyData)-10)["close"],timeperiod=40).tail(1).iloc[0]
4148
+ recent_sma_50 = pktalib.SMA(reversedData["close"],timeperiod=50).tail(1).iloc[0]
4149
+ w_wma_8 = pktalib.WMA(weeklyData["close"],timeperiod=8).tail(1).iloc[0]
4150
+ w_sma_8 = pktalib.SMA(weeklyData["close"],timeperiod=8).tail(1).iloc[0]
4139
4151
  numPreviousCandles = 20
4140
4152
  pullbackData = data.head(numPreviousCandles)
4141
- pullbackData.loc[:,'PullBack'] = pullbackData["Close"].lt(pullbackData["Open"]) #.shift(periods=1)) #& data["Low"].lt(data["Low"].shift(periods=1))
4153
+ pullbackData.loc[:,'PullBack'] = pullbackData["close"].lt(pullbackData["open"]) #.shift(periods=1)) #& data["low"].lt(data["low"].shift(periods=1))
4142
4154
  shrinkedVolData = pullbackData[pullbackData["PullBack"] == True].head(numPreviousCandles)
4143
- recentLargestVolume = max(pullbackData[pullbackData["PullBack"] == False].head(3)["Volume"])
4144
- # pullbackData.loc[:,'PBVolRatio'] = pullbackData["Volume"]/recentLargestVolume
4155
+ recentLargestVolume = max(pullbackData[pullbackData["PullBack"] == False].head(3)["volume"])
4156
+ # pullbackData.loc[:,'PBVolRatio'] = pullbackData["volume"]/recentLargestVolume
4145
4157
  volInPreviousPullbacksShrinked = False
4146
4158
  if not shrinkedVolData.empty:
4147
4159
  index = 0
4148
4160
  while index < len(shrinkedVolData):
4149
- volInPreviousPullbacksShrinked = shrinkedVolData["Volume"].iloc[index] < self.configManager.vcpVolumeContractionRatio * recentLargestVolume
4161
+ volInPreviousPullbacksShrinked = shrinkedVolData["volume"].iloc[index] < self.configManager.vcpVolumeContractionRatio * recentLargestVolume
4150
4162
  if not volInPreviousPullbacksShrinked:
4151
4163
  break
4152
4164
  index += 1
@@ -4187,18 +4199,18 @@ class ScreeningStatistics:
4187
4199
  # Either the rolling volume of past 20 sessions or today's volume should be > min volume
4188
4200
  hasMinimumVolume = (
4189
4201
  recent["VolMA"].iloc[0] >= minVolume
4190
- or recent["Volume"].iloc[0] >= minVolume
4202
+ or recent["volume"].iloc[0] >= minVolume
4191
4203
  )
4192
4204
  if recent["VolMA"].iloc[0] == 0: # Handles Divide by 0 warning
4193
- saveDict["Volume"] = 0 # "Unknown"
4194
- screenDict["Volume"] = 0
4205
+ saveDict["volume"] = 0 # "Unknown"
4206
+ screenDict["volume"] = 0
4195
4207
  return False, hasMinimumVolume
4196
- ratio = round(recent["Volume"].iloc[0] / recent["VolMA"].iloc[0], 2)
4197
- saveDict["Volume"] = ratio
4208
+ ratio = round(recent["volume"].iloc[0] / recent["VolMA"].iloc[0], 2)
4209
+ saveDict["volume"] = ratio
4198
4210
  if ratio >= volumeRatio and ratio != np.nan and (not math.isinf(ratio)):
4199
- screenDict["Volume"] = ratio
4211
+ screenDict["volume"] = ratio
4200
4212
  return True, hasMinimumVolume
4201
- screenDict["Volume"] = ratio
4213
+ screenDict["volume"] = ratio
4202
4214
  return False, hasMinimumVolume
4203
4215
 
4204
4216
  # Find if stock is validating volume spread analysis
@@ -4213,23 +4225,23 @@ class ScreeningStatistics:
4213
4225
  try:
4214
4226
  # Check for previous RED candles
4215
4227
  # Current candle = 0th, Previous Candle = 1st for following logic
4216
- if data.iloc[1]["Open"] >= data.iloc[1]["Close"]:
4217
- spread1 = abs(data.iloc[1]["Open"] - data.iloc[1]["Close"])
4218
- spread0 = abs(data.iloc[0]["Open"] - data.iloc[0]["Close"])
4228
+ if data.iloc[1]["open"] >= data.iloc[1]["close"]:
4229
+ spread1 = abs(data.iloc[1]["open"] - data.iloc[1]["close"])
4230
+ spread0 = abs(data.iloc[0]["open"] - data.iloc[0]["close"])
4219
4231
  lower_wick_spread0 = (
4220
- max(data.iloc[0]["Open"], data.iloc[0]["Close"])
4221
- - data.iloc[0]["Low"]
4232
+ max(data.iloc[0]["open"], data.iloc[0]["close"])
4233
+ - data.iloc[0]["low"]
4222
4234
  )
4223
- vol1 = data.iloc[1]["Volume"]
4224
- vol0 = data.iloc[0]["Volume"]
4235
+ vol1 = data.iloc[1]["volume"]
4236
+ vol0 = data.iloc[0]["volume"]
4225
4237
  saved = self.findCurrentSavedValue(screenDict, saveDict, "Pattern")
4226
4238
  if (
4227
4239
  spread0 > spread1
4228
4240
  and vol0 < vol1
4229
- and data.iloc[0]["Volume"] < data.iloc[0]["VolMA"]
4230
- and data.iloc[0]["Close"] <= data.iloc[1]["Open"]
4241
+ and data.iloc[0]["volume"] < data.iloc[0]["VolMA"]
4242
+ and data.iloc[0]["close"] <= data.iloc[1]["open"]
4231
4243
  and spread0 < lower_wick_spread0
4232
- and data.iloc[0]["Volume"] <= int(data.iloc[1]["Volume"] * 0.75)
4244
+ and data.iloc[0]["volume"] <= int(data.iloc[1]["volume"] * 0.75)
4233
4245
  ):
4234
4246
  screenDict["Pattern"] = (
4235
4247
  saved[0]
@@ -4242,8 +4254,8 @@ class ScreeningStatistics:
4242
4254
  if (
4243
4255
  spread0 < spread1
4244
4256
  and vol0 > vol1
4245
- and data.iloc[0]["Volume"] > data.iloc[0]["VolMA"]
4246
- and data.iloc[0]["Close"] <= data.iloc[1]["Open"]
4257
+ and data.iloc[0]["volume"] > data.iloc[0]["VolMA"]
4258
+ and data.iloc[0]["close"] <= data.iloc[1]["open"]
4247
4259
  ):
4248
4260
  screenDict["Pattern"] = (
4249
4261
  saved[0]