Upload 42 files
Browse files- __pycache__/kotak_neo.cpython-311.pyc +0 -0
- kotak_neo.py +70 -26
__pycache__/kotak_neo.cpython-311.pyc
CHANGED
|
Binary files a/__pycache__/kotak_neo.cpython-311.pyc and b/__pycache__/kotak_neo.cpython-311.pyc differ
|
|
|
kotak_neo.py
CHANGED
|
@@ -113,6 +113,16 @@ def _is_nse_trading_day(day: date) -> bool:
|
|
| 113 |
return not calendar.schedule(start_date=day, end_date=day).empty
|
| 114 |
|
| 115 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 116 |
def _file_version(path: Path) -> tuple[str, int | None, int | None]:
|
| 117 |
try:
|
| 118 |
stat = path.stat()
|
|
@@ -487,7 +497,25 @@ class KotakNeoManager:
|
|
| 487 |
quote_open = _first_market_number(item.get("openingPrice"), item.get("open"), item.get("o"))
|
| 488 |
quote_high = _first_market_number(item.get("high"), item.get("highPrice"), item.get("h"))
|
| 489 |
quote_low = _first_market_number(item.get("low"), item.get("lowPrice"), item.get("l"))
|
| 490 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 491 |
close = live_stats["previous_close"]
|
| 492 |
change_base = live_stats["return_base"]
|
| 493 |
change = None
|
|
@@ -520,6 +548,8 @@ class KotakNeoManager:
|
|
| 520 |
"return_basis": live_stats["return_basis"],
|
| 521 |
"market_open": live_stats["market_open"],
|
| 522 |
"is_trading_session": live_stats["is_trading_session"],
|
|
|
|
|
|
|
| 523 |
"exchange_feed_time": _first_text(item.get("tvalue"), item.get("updRecvTm"), item.get("hsUpTm")),
|
| 524 |
"as_of": _utc_now_iso(),
|
| 525 |
"source": {
|
|
@@ -546,59 +576,71 @@ class KotakNeoManager:
|
|
| 546 |
live_open: float | None = None,
|
| 547 |
live_high: float | None = None,
|
| 548 |
live_low: float | None = None,
|
|
|
|
| 549 |
) -> dict[str, Any]:
|
| 550 |
today = now_ist.date()
|
| 551 |
is_trading_session = _is_nse_trading_day(today)
|
| 552 |
market_open = is_trading_session and MARKET_OPEN_TIME <= now_ist.time() < MARKET_CLOSE_TIME
|
|
|
|
|
|
|
|
|
|
| 553 |
|
| 554 |
daily = _load_nifty_daily_frame(_file_version(NIFTY_1D_PATH))
|
| 555 |
|
| 556 |
previous_close = None
|
| 557 |
-
|
| 558 |
-
|
| 559 |
-
|
| 560 |
-
|
| 561 |
if not previous_daily.empty:
|
| 562 |
previous_row = previous_daily.iloc[-1]
|
| 563 |
previous_close = _to_float(previous_row["close"])
|
| 564 |
-
previous_high = _to_float(previous_row["high"])
|
| 565 |
-
previous_low = _to_float(previous_row["low"])
|
| 566 |
|
| 567 |
-
|
| 568 |
-
|
| 569 |
-
|
| 570 |
-
|
| 571 |
|
| 572 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 573 |
|
| 574 |
if session_started:
|
| 575 |
-
|
| 576 |
-
|
| 577 |
-
|
| 578 |
|
| 579 |
-
if
|
| 580 |
minute = _load_nifty_minute_frame(_file_version(NIFTY_1M_PATH))
|
| 581 |
today_minute = minute[minute["date"].dt.date == today]
|
| 582 |
if not today_minute.empty:
|
| 583 |
-
|
| 584 |
minute_high = pd.to_numeric(today_minute["high"], errors="coerce").max()
|
| 585 |
minute_low = pd.to_numeric(today_minute["low"], errors="coerce").min()
|
| 586 |
-
|
| 587 |
-
|
| 588 |
-
|
|
|
|
|
|
|
|
|
|
| 589 |
|
| 590 |
if session_started:
|
| 591 |
-
range_high = max([value for value in [
|
| 592 |
-
range_low = min([value for value in [
|
| 593 |
-
return_base =
|
| 594 |
return_basis = "open"
|
| 595 |
else:
|
| 596 |
-
range_high =
|
| 597 |
-
range_low =
|
| 598 |
return_base = previous_close
|
| 599 |
return_basis = "previous_close"
|
| 600 |
if last_traded_price is None:
|
| 601 |
-
last_traded_price =
|
| 602 |
|
| 603 |
return {
|
| 604 |
"previous_close": previous_close,
|
|
@@ -608,6 +650,8 @@ class KotakNeoManager:
|
|
| 608 |
"range_low": range_low,
|
| 609 |
"market_open": market_open,
|
| 610 |
"is_trading_session": is_trading_session,
|
|
|
|
|
|
|
| 611 |
}
|
| 612 |
|
| 613 |
def _ensure_authenticated_locked(self) -> None:
|
|
|
|
| 113 |
return not calendar.schedule(start_date=day, end_date=day).empty
|
| 114 |
|
| 115 |
|
| 116 |
+
@lru_cache(maxsize=64)
|
| 117 |
+
def _previous_nse_trading_day(day: date) -> date:
|
| 118 |
+
candidate = day
|
| 119 |
+
for _ in range(21):
|
| 120 |
+
candidate = date.fromordinal(candidate.toordinal() - 1)
|
| 121 |
+
if _is_nse_trading_day(candidate):
|
| 122 |
+
return candidate
|
| 123 |
+
return candidate
|
| 124 |
+
|
| 125 |
+
|
| 126 |
def _file_version(path: Path) -> tuple[str, int | None, int | None]:
|
| 127 |
try:
|
| 128 |
stat = path.stat()
|
|
|
|
| 497 |
quote_open = _first_market_number(item.get("openingPrice"), item.get("open"), item.get("o"))
|
| 498 |
quote_high = _first_market_number(item.get("high"), item.get("highPrice"), item.get("h"))
|
| 499 |
quote_low = _first_market_number(item.get("low"), item.get("lowPrice"), item.get("l"))
|
| 500 |
+
quote_previous_close = _first_market_number(
|
| 501 |
+
item.get("previous_close"),
|
| 502 |
+
item.get("previousClose"),
|
| 503 |
+
item.get("prev_close"),
|
| 504 |
+
item.get("prevClose"),
|
| 505 |
+
item.get("previousClosePrice"),
|
| 506 |
+
item.get("prevClosePrice"),
|
| 507 |
+
item.get("close"),
|
| 508 |
+
item.get("c"),
|
| 509 |
+
item.get("ic"),
|
| 510 |
+
)
|
| 511 |
+
live_stats = self._load_nifty50_reference_stats(
|
| 512 |
+
now_ist,
|
| 513 |
+
last_traded_price,
|
| 514 |
+
quote_open,
|
| 515 |
+
quote_high,
|
| 516 |
+
quote_low,
|
| 517 |
+
quote_previous_close,
|
| 518 |
+
)
|
| 519 |
close = live_stats["previous_close"]
|
| 520 |
change_base = live_stats["return_base"]
|
| 521 |
change = None
|
|
|
|
| 548 |
"return_basis": live_stats["return_basis"],
|
| 549 |
"market_open": live_stats["market_open"],
|
| 550 |
"is_trading_session": live_stats["is_trading_session"],
|
| 551 |
+
"quote_session_date": live_stats["quote_session_date"],
|
| 552 |
+
"previous_session_date": live_stats["previous_session_date"],
|
| 553 |
"exchange_feed_time": _first_text(item.get("tvalue"), item.get("updRecvTm"), item.get("hsUpTm")),
|
| 554 |
"as_of": _utc_now_iso(),
|
| 555 |
"source": {
|
|
|
|
| 576 |
live_open: float | None = None,
|
| 577 |
live_high: float | None = None,
|
| 578 |
live_low: float | None = None,
|
| 579 |
+
live_previous_close: float | None = None,
|
| 580 |
) -> dict[str, Any]:
|
| 581 |
today = now_ist.date()
|
| 582 |
is_trading_session = _is_nse_trading_day(today)
|
| 583 |
market_open = is_trading_session and MARKET_OPEN_TIME <= now_ist.time() < MARKET_CLOSE_TIME
|
| 584 |
+
session_started = is_trading_session and now_ist.time() >= MARKET_OPEN_TIME
|
| 585 |
+
quote_session_date = today if session_started else _previous_nse_trading_day(today)
|
| 586 |
+
previous_session_date = _previous_nse_trading_day(quote_session_date)
|
| 587 |
|
| 588 |
daily = _load_nifty_daily_frame(_file_version(NIFTY_1D_PATH))
|
| 589 |
|
| 590 |
previous_close = None
|
| 591 |
+
session_daily = daily[daily["date"] == quote_session_date]
|
| 592 |
+
previous_daily = daily[daily["date"] == previous_session_date]
|
| 593 |
+
if previous_daily.empty:
|
| 594 |
+
previous_daily = daily[daily["date"] < quote_session_date]
|
| 595 |
if not previous_daily.empty:
|
| 596 |
previous_row = previous_daily.iloc[-1]
|
| 597 |
previous_close = _to_float(previous_row["close"])
|
|
|
|
|
|
|
| 598 |
|
| 599 |
+
session_open = _to_float(session_daily.iloc[-1]["open"]) if not session_daily.empty else None
|
| 600 |
+
session_high = _to_float(session_daily.iloc[-1]["high"]) if not session_daily.empty else None
|
| 601 |
+
session_low = _to_float(session_daily.iloc[-1]["low"]) if not session_daily.empty else None
|
| 602 |
+
session_close = _to_float(session_daily.iloc[-1]["close"]) if not session_daily.empty else None
|
| 603 |
|
| 604 |
+
if live_previous_close is not None:
|
| 605 |
+
is_same_as_static_ltp = (
|
| 606 |
+
not session_started
|
| 607 |
+
and last_traded_price is not None
|
| 608 |
+
and abs(live_previous_close - last_traded_price) < 0.01
|
| 609 |
+
)
|
| 610 |
+
if not is_same_as_static_ltp:
|
| 611 |
+
previous_close = live_previous_close
|
| 612 |
|
| 613 |
if session_started:
|
| 614 |
+
session_open = live_open or session_open
|
| 615 |
+
session_high = live_high or session_high
|
| 616 |
+
session_low = live_low or session_low
|
| 617 |
|
| 618 |
+
if session_open is None or session_high is None or session_low is None:
|
| 619 |
minute = _load_nifty_minute_frame(_file_version(NIFTY_1M_PATH))
|
| 620 |
today_minute = minute[minute["date"].dt.date == today]
|
| 621 |
if not today_minute.empty:
|
| 622 |
+
session_open = _to_float(today_minute.iloc[0]["open"]) or session_open
|
| 623 |
minute_high = pd.to_numeric(today_minute["high"], errors="coerce").max()
|
| 624 |
minute_low = pd.to_numeric(today_minute["low"], errors="coerce").min()
|
| 625 |
+
session_high = _to_float(minute_high) or session_high
|
| 626 |
+
session_low = _to_float(minute_low) or session_low
|
| 627 |
+
session_close = _to_float(today_minute.iloc[-1]["close"]) or session_close
|
| 628 |
+
else:
|
| 629 |
+
session_high = live_high or session_high
|
| 630 |
+
session_low = live_low or session_low
|
| 631 |
|
| 632 |
if session_started:
|
| 633 |
+
range_high = max([value for value in [session_high, last_traded_price] if value is not None], default=None)
|
| 634 |
+
range_low = min([value for value in [session_low, last_traded_price] if value is not None], default=None)
|
| 635 |
+
return_base = session_open
|
| 636 |
return_basis = "open"
|
| 637 |
else:
|
| 638 |
+
range_high = session_high
|
| 639 |
+
range_low = session_low
|
| 640 |
return_base = previous_close
|
| 641 |
return_basis = "previous_close"
|
| 642 |
if last_traded_price is None:
|
| 643 |
+
last_traded_price = session_close
|
| 644 |
|
| 645 |
return {
|
| 646 |
"previous_close": previous_close,
|
|
|
|
| 650 |
"range_low": range_low,
|
| 651 |
"market_open": market_open,
|
| 652 |
"is_trading_session": is_trading_session,
|
| 653 |
+
"quote_session_date": quote_session_date.isoformat(),
|
| 654 |
+
"previous_session_date": previous_session_date.isoformat(),
|
| 655 |
}
|
| 656 |
|
| 657 |
def _ensure_authenticated_locked(self) -> None:
|