Jitendra12421 commited on
Commit
8fe2df2
·
verified ·
1 Parent(s): 21e57c2

Upload folder using huggingface_hub

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. app.py +94 -0
  2. core/__init__.py +6 -0
  3. core/__pycache__/__init__.cpython-311.pyc +0 -0
  4. core/__pycache__/config.cpython-311.pyc +0 -0
  5. core/__pycache__/features.cpython-311.pyc +0 -0
  6. core/__pycache__/groww.cpython-311.pyc +0 -0
  7. core/__pycache__/models.cpython-311.pyc +0 -0
  8. core/__pycache__/taxes.cpython-311.pyc +0 -0
  9. core/config.py +37 -0
  10. core/features.py +202 -0
  11. core/groww.py +112 -0
  12. core/models.py +117 -0
  13. core/taxes.py +50 -0
  14. data/live_trades.json +45 -0
  15. data/minute_ohlcv/ADANIENT_minute.parquet +3 -0
  16. data/minute_ohlcv/ADANIPORTS_minute.parquet +3 -0
  17. data/minute_ohlcv/APOLLOHOSP_minute.parquet +3 -0
  18. data/minute_ohlcv/ASIANPAINT_minute.parquet +3 -0
  19. data/minute_ohlcv/AXISBANK_minute.parquet +3 -0
  20. data/minute_ohlcv/BAJAJ-AUTO_minute.parquet +3 -0
  21. data/minute_ohlcv/BAJAJFINSV_minute.parquet +3 -0
  22. data/minute_ohlcv/BAJFINANCE_minute.parquet +3 -0
  23. data/minute_ohlcv/BHARTIARTL_minute.parquet +3 -0
  24. data/minute_ohlcv/BPCL_minute.parquet +3 -0
  25. data/minute_ohlcv/BRITANNIA_minute.parquet +3 -0
  26. data/minute_ohlcv/CIPLA_minute.parquet +3 -0
  27. data/minute_ohlcv/COALINDIA_minute.parquet +3 -0
  28. data/minute_ohlcv/DIVISLAB_minute.parquet +3 -0
  29. data/minute_ohlcv/DRREDDY_minute.parquet +3 -0
  30. data/minute_ohlcv/EICHERMOT_minute.parquet +3 -0
  31. data/minute_ohlcv/GRASIM_minute.parquet +3 -0
  32. data/minute_ohlcv/HCLTECH_minute.parquet +3 -0
  33. data/minute_ohlcv/HDFCBANK_minute.parquet +3 -0
  34. data/minute_ohlcv/HDFCLIFE_minute.parquet +3 -0
  35. data/minute_ohlcv/HEROMOTOCO_minute.parquet +3 -0
  36. data/minute_ohlcv/HINDALCO_minute.parquet +3 -0
  37. data/minute_ohlcv/HINDUNILVR_minute.parquet +3 -0
  38. data/minute_ohlcv/ICICIBANK_minute.parquet +3 -0
  39. data/minute_ohlcv/INDUSINDBK_minute.parquet +3 -0
  40. data/minute_ohlcv/INFY_minute.parquet +3 -0
  41. data/minute_ohlcv/ITC_minute.parquet +3 -0
  42. data/minute_ohlcv/JSWSTEEL_minute.parquet +3 -0
  43. data/minute_ohlcv/KOTAKBANK_minute.parquet +3 -0
  44. data/minute_ohlcv/LTIM_minute.parquet +3 -0
  45. data/minute_ohlcv/LT_minute.parquet +3 -0
  46. data/minute_ohlcv/MARUTI_minute.parquet +3 -0
  47. data/minute_ohlcv/MM_minute.parquet +3 -0
  48. data/minute_ohlcv/NESTLEIND_minute.parquet +3 -0
  49. data/minute_ohlcv/NTPC_minute.parquet +3 -0
  50. data/minute_ohlcv/ONGC_minute.parquet +3 -0
app.py CHANGED
@@ -6,10 +6,13 @@ from fastapi.middleware.cors import CORSMiddleware
6
  from zoneinfo import ZoneInfo
7
  from data_updater import update_daily_data, is_trading_day
8
  from forecaster_engine import generate_predictions
 
9
 
10
  IST = ZoneInfo("Asia/Kolkata")
11
  MARKET_CLOSE_BUFFER = time(15, 45) # Update runs after 3:45 PM
 
12
  PREDICTIONS_FILE = os.path.join(os.path.dirname(__file__), "predictions.json")
 
13
 
14
  app = FastAPI(title="HF NIFTY Forecaster Backend")
15
 
@@ -33,6 +36,16 @@ def run_update_pipeline():
33
  except Exception as e:
34
  print(f"Pipeline error: {e}")
35
 
 
 
 
 
 
 
 
 
 
 
36
  @app.get("/predictions")
37
  def get_predictions():
38
  if not os.path.exists(PREDICTIONS_FILE):
@@ -62,6 +75,87 @@ def cron_trigger(background_tasks: BackgroundTasks):
62
 
63
  return {"status": "triggered", "message": "Update and forecast pipeline started in the background."}
64
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65
  @app.get("/health")
66
  def health_check():
67
  return {"status": "alive", "server_time_ist": datetime.now(IST).isoformat()}
 
6
  from zoneinfo import ZoneInfo
7
  from data_updater import update_daily_data, is_trading_day
8
  from forecaster_engine import generate_predictions
9
+ from signal_generator import generate_signals
10
 
11
  IST = ZoneInfo("Asia/Kolkata")
12
  MARKET_CLOSE_BUFFER = time(15, 45) # Update runs after 3:45 PM
13
+ SIGNAL_TIME = time(9, 30) # Signal generation at 9:30 AM
14
  PREDICTIONS_FILE = os.path.join(os.path.dirname(__file__), "predictions.json")
15
+ SIGNALS_FILE = os.path.join(os.path.dirname(__file__), "signals.json")
16
 
17
  app = FastAPI(title="HF NIFTY Forecaster Backend")
18
 
 
36
  except Exception as e:
37
  print(f"Pipeline error: {e}")
38
 
39
+ def run_signal_pipeline():
40
+ """Run the 5-ticker signal generator."""
41
+ try:
42
+ result = generate_signals()
43
+ print(f"Signal generation result: {result.get('primary_signal', {}).get('action', 'UNKNOWN')}")
44
+ except Exception as e:
45
+ print(f"Signal pipeline error: {e}")
46
+
47
+ # ── Existing Endpoints ───────────────────────────────────────────────────────
48
+
49
  @app.get("/predictions")
50
  def get_predictions():
51
  if not os.path.exists(PREDICTIONS_FILE):
 
75
 
76
  return {"status": "triggered", "message": "Update and forecast pipeline started in the background."}
77
 
78
+ # ── NEW: Signal Generator Endpoints ──────────────────────────────────────────
79
+
80
+ @app.get("/signals")
81
+ def get_signals():
82
+ """Get the latest generated trading signals for the 5-ticker system."""
83
+ if not os.path.exists(SIGNALS_FILE):
84
+ raise HTTPException(status_code=404, detail="Signals not yet generated. Trigger /cron/signal first.")
85
+
86
+ with open(SIGNALS_FILE, "r") as f:
87
+ data = json.load(f)
88
+
89
+ return data
90
+
91
+ @app.post("/cron/signal")
92
+ def signal_trigger(background_tasks: BackgroundTasks):
93
+ """
94
+ Trigger signal generation at 9:30 AM IST.
95
+ Trains models, fetches live candles, generates BUY/SELL signals.
96
+ """
97
+ now = datetime.now(IST)
98
+ today = now.date()
99
+
100
+ # Check if it's a trading day
101
+ if not is_trading_day(today):
102
+ return {"status": "skipped", "reason": f"{today} is a holiday or weekend"}
103
+
104
+ # Run signal generation in background
105
+ background_tasks.add_task(run_signal_pipeline)
106
+
107
+ return {
108
+ "status": "triggered",
109
+ "message": "Signal generation pipeline started. Check /signals for results.",
110
+ "trigger_time": now.isoformat(),
111
+ }
112
+
113
+ @app.post("/signals/generate-now")
114
+ def force_signal_generation(background_tasks: BackgroundTasks):
115
+ """Force signal generation immediately, bypassing time checks."""
116
+ background_tasks.add_task(run_signal_pipeline)
117
+ return {
118
+ "status": "triggered",
119
+ "message": "Signal generation forced. Check /signals for results.",
120
+ "trigger_time": datetime.now(IST).isoformat(),
121
+ }
122
+
123
+ @app.get("/portfolio")
124
+ def get_portfolio():
125
+ """Get current portfolio status from trade journal."""
126
+ trade_log = os.path.join(os.path.dirname(__file__), "data", "live_trades.json")
127
+ if not os.path.exists(trade_log):
128
+ return {
129
+ "starting_capital": 3692.0,
130
+ "current_capital": 3692.0,
131
+ "total_pnl": 0,
132
+ "trades_count": 0,
133
+ "win_rate": 0,
134
+ }
135
+
136
+ with open(trade_log, "r") as f:
137
+ data = json.load(f)
138
+
139
+ trades = data.get("trades", [])
140
+ starting_cap = data.get("starting_capital", 3692.0)
141
+
142
+ cap = starting_cap
143
+ for t in trades:
144
+ if "net_pnl" in t and t["net_pnl"] is not None:
145
+ cap += t["net_pnl"]
146
+
147
+ n_closed = len([t for t in trades if t.get("net_pnl") is not None])
148
+ n_wins = len([t for t in trades if (t.get("net_pnl") or 0) > 0])
149
+
150
+ return {
151
+ "starting_capital": starting_cap,
152
+ "current_capital": round(cap, 2),
153
+ "total_pnl": round(cap - starting_cap, 2),
154
+ "trades_count": n_closed,
155
+ "win_rate": round(n_wins / n_closed * 100, 1) if n_closed > 0 else 0,
156
+ "last_updated": data.get("last_updated"),
157
+ }
158
+
159
  @app.get("/health")
160
  def health_check():
161
  return {"status": "alive", "server_time_ist": datetime.now(IST).isoformat()}
core/__init__.py ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ # core/__init__.py
2
+ from core.config import *
3
+ from core.taxes import calculate_taxes_and_slippage
4
+ from core.features import extract_semantic_features, extract_sequential_features
5
+ from core.models import build_pipeline_map, train_models
6
+ from core.groww import fetch_groww_candles
core/__pycache__/__init__.cpython-311.pyc ADDED
Binary file (571 Bytes). View file
 
core/__pycache__/config.cpython-311.pyc ADDED
Binary file (1.09 kB). View file
 
core/__pycache__/features.cpython-311.pyc ADDED
Binary file (13.4 kB). View file
 
core/__pycache__/groww.cpython-311.pyc ADDED
Binary file (5.66 kB). View file
 
core/__pycache__/models.cpython-311.pyc ADDED
Binary file (4.82 kB). View file
 
core/__pycache__/taxes.cpython-311.pyc ADDED
Binary file (1.63 kB). View file
 
core/config.py ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Central configuration for the intraday trading system.
3
+ All constants, paths, and model architecture definitions live here.
4
+ """
5
+
6
+ from pathlib import Path
7
+
8
+ # ── Paths ──
9
+ PROJECT_DIR = Path(__file__).resolve().parent.parent
10
+ DATA_DIR = PROJECT_DIR / "data" / "minute_ohlcv"
11
+ TRADE_LOG = PROJECT_DIR / "data" / "live_trades.json"
12
+ LOG_FILE = PROJECT_DIR / "logs" / "live_trader.log"
13
+
14
+ # ── Universe ──
15
+ TICKERS = ["INFY", "ASIANPAINT", "TECHM", "POWERGRID", "ONGC"]
16
+
17
+ # ── Capital & Risk ──
18
+ STARTING_CAP = 3692.0
19
+ LEVERAGE = 5.0
20
+ MIN_CONFIDENCE = 0.50
21
+
22
+ # ── Schedule (IST) ──
23
+ SIGNAL_HOUR = 9
24
+ SIGNAL_MINUTE = 31
25
+
26
+ # ── Pipeline mapping ──
27
+ # Defines which feature extractor and model architecture each ticker uses.
28
+ # Format: { ticker: (feature_type, model_key) }
29
+ # feature_type : "semantic" | "sequential"
30
+ # model_key : "ensemble" | "lr_pipeline"
31
+ PIPELINE_MAP = {
32
+ "INFY": ("semantic", "ensemble"),
33
+ "TECHM": ("sequential", "kbest15_lr"),
34
+ "ASIANPAINT": ("sequential", "ensemble"),
35
+ "POWERGRID": ("sequential", "ensemble"),
36
+ "ONGC": ("semantic", "lr_pipeline"),
37
+ }
core/features.py ADDED
@@ -0,0 +1,202 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Feature extraction from 1-min OHLCV DataFrames.
3
+
4
+ Two pipelines:
5
+ - semantic: Hand-crafted morning indicators (gap, VWAP deviation, momentum, etc.)
6
+ - sequential: Raw normalised return and volume vectors for the 09:15-09:30 window.
7
+
8
+ Both return (X, y, metadata) where:
9
+ X : pd.DataFrame of features, indexed by date
10
+ y : pd.Series of binary labels (1 = price up 09:30->15:10)
11
+ metadata : dict[date] -> { c_0930, h_0930, l_0930, v_0930, c_1510, h_1510, l_1510 }
12
+ """
13
+
14
+ import numpy as np
15
+ import pandas as pd
16
+
17
+
18
+ # ── Helpers ──────────────────────────────────────────────────────────────────
19
+
20
+ def _safe_fill(arr):
21
+ """Forward-fill then back-fill NaNs in a 1-D array."""
22
+ return pd.Series(arr).ffill().bfill().values
23
+
24
+
25
+ # ── Semantic features ────────────────────────────────────────────────────────
26
+
27
+ def extract_semantic_features(df):
28
+ """
29
+ Compute high-level morning indicators from the 09:15-09:30 candle window.
30
+
31
+ Features: gap, return_16m, return_first_5m, return_next_11m, std_dev,
32
+ range_pct, upper_shadow, lower_shadow, total_vol, vwap_dev,
33
+ price_momentum, vol_momentum, morning_trend.
34
+ """
35
+ df = df.copy()
36
+ df["time"] = df.index.time
37
+ df["date_only"] = df.index.date
38
+ required_times = (
39
+ pd.date_range("09:15", "09:30", freq="min").time.tolist()
40
+ + [pd.to_datetime("15:10").time()]
41
+ )
42
+ df = df[~df.index.duplicated(keep="first")]
43
+
44
+ daily_close = df.groupby("date_only")["close"].last()
45
+ prev_daily_close = daily_close.shift(1)
46
+
47
+ # Compute morning session dip/peak (09:31 to 12:00) for limit-order entries
48
+ time_0931 = pd.to_datetime("09:31").time()
49
+ time_1200 = pd.to_datetime("12:00").time()
50
+ df_morning = df[(df["time"] >= time_0931) & (df["time"] <= time_1200)]
51
+ morning_low_per_date = df_morning.groupby("date_only")["low"].min()
52
+ morning_high_per_date = df_morning.groupby("date_only")["high"].max()
53
+
54
+ df_filtered = df[df["time"].isin(required_times)].copy()
55
+ pivot_close = df_filtered.pivot(index="date_only", columns="time", values="close")
56
+ pivot_open = df_filtered.pivot(index="date_only", columns="time", values="open")
57
+ pivot_high = df_filtered.pivot(index="date_only", columns="time", values="high")
58
+ pivot_low = df_filtered.pivot(index="date_only", columns="time", values="low")
59
+ pivot_vol = df_filtered.pivot(index="date_only", columns="time", values="volume")
60
+
61
+ time_0930 = pd.to_datetime("09:30").time()
62
+ time_1510 = pd.to_datetime("15:10").time()
63
+
64
+ if time_0930 not in pivot_close.columns:
65
+ return None, None, None
66
+
67
+ pivot_close = pivot_close.dropna(subset=[time_0930])
68
+ valid_dates = pivot_close.index
69
+ times_15m = pd.date_range("09:15", "09:30", freq="min").time
70
+
71
+ feature_dicts = []
72
+ metadata = {}
73
+
74
+ for date in valid_dates:
75
+ f = {}
76
+ c_series = _safe_fill(pivot_close.loc[date, times_15m].values.astype(float))
77
+ o_series = _safe_fill(pivot_open.loc[date, times_15m].values.astype(float))
78
+ h_series = _safe_fill(pivot_high.loc[date, times_15m].values.astype(float))
79
+ l_series = _safe_fill(pivot_low.loc[date, times_15m].values.astype(float))
80
+ v_series = pd.Series(pivot_vol.loc[date, times_15m].values.astype(float)).fillna(0).values
81
+
82
+ o_915 = o_series[0]
83
+ c_930 = c_series[-1]
84
+ c_919 = c_series[4] if len(c_series) > 4 else c_series[-1]
85
+
86
+ pdc = prev_daily_close.get(date, np.nan)
87
+ f["gap"] = 0 if (pd.isna(pdc) or pdc == 0) else (o_915 / pdc) - 1.0
88
+ f["return_16m"] = (c_930 / o_915) - 1.0 if o_915 != 0 else 0
89
+ f["return_first_5m"] = (c_919 / o_915) - 1.0 if o_915 != 0 else 0
90
+ f["return_next_11m"] = (c_930 / c_919) - 1.0 if c_919 != 0 else 0
91
+ f["std_dev"] = np.std(c_series / (o_915 + 1e-8))
92
+
93
+ max_h = np.max(h_series)
94
+ min_l = np.min(l_series)
95
+ f["range_pct"] = (max_h - min_l) / (o_915 + 1e-8)
96
+ f["upper_shadow"] = (max_h - max(o_915, c_930)) / (o_915 + 1e-8)
97
+ f["lower_shadow"] = (min(o_915, c_930) - min_l) / (o_915 + 1e-8)
98
+ f["total_vol"] = np.sum(v_series)
99
+
100
+ vwap = np.sum(((h_series + l_series + c_series) / 3.0) * v_series) / (np.sum(v_series) + 1e-8)
101
+ f["vwap_dev"] = (c_930 / vwap) - 1.0 if vwap != 0 else 0
102
+ f["price_momentum"] = (c_series[-1] - c_series[-3]) / (c_series[-3] + 1e-8)
103
+ f["vol_momentum"] = (v_series[-1] - v_series[-3]) / (v_series[-3] + 1e-8)
104
+ f["morning_trend"] = np.polyfit(np.arange(len(c_series)), c_series, 1)[0]
105
+
106
+ feature_dicts.append(f)
107
+
108
+ metadata[date] = {
109
+ "c_0930": c_930,
110
+ "h_0930": float(pivot_high.loc[date, time_0930]) if time_0930 in pivot_high.columns else c_930,
111
+ "l_0930": float(pivot_low.loc[date, time_0930]) if time_0930 in pivot_low.columns else c_930,
112
+ "v_0930": float(pivot_vol.loc[date, time_0930]) if time_0930 in pivot_vol.columns else 0,
113
+ "c_1510": float(pivot_close.loc[date, time_1510]) if time_1510 in pivot_close.columns else c_930,
114
+ "h_1510": float(pivot_high.loc[date, time_1510]) if time_1510 in pivot_high.columns else c_930,
115
+ "l_1510": float(pivot_low.loc[date, time_1510]) if time_1510 in pivot_low.columns else c_930,
116
+ "dip_low": float(morning_low_per_date.get(date, c_930)),
117
+ "peak_high": float(morning_high_per_date.get(date, c_930)),
118
+ }
119
+
120
+ X = pd.DataFrame(feature_dicts, index=valid_dates).fillna(0)
121
+
122
+ if time_1510 in pivot_close.columns:
123
+ target = (pivot_close[time_1510] > pivot_close[time_0930]).astype(int)
124
+ else:
125
+ target = pd.Series(0, index=valid_dates)
126
+
127
+ return X, target, metadata
128
+
129
+
130
+ # ── Sequential features ──────────────────────────────────────────────────────
131
+
132
+ def extract_sequential_features(df):
133
+ """
134
+ Compute normalised return and raw volume vectors for each minute
135
+ in the 09:15-09:30 window, relative to the 09:30 close.
136
+ """
137
+ df = df.copy()
138
+ df["time"] = df.index.time
139
+ df["date_only"] = df.index.date
140
+ required_times = (
141
+ pd.date_range("09:15", "09:30", freq="min").time.tolist()
142
+ + [pd.to_datetime("15:10").time()]
143
+ )
144
+ df = df[~df.index.duplicated(keep="first")]
145
+
146
+ # Compute morning session dip/peak (09:31 to 12:00) for limit-order entries
147
+ time_0931 = pd.to_datetime("09:31").time()
148
+ time_1200 = pd.to_datetime("12:00").time()
149
+ df_morning = df[(df["time"] >= time_0931) & (df["time"] <= time_1200)]
150
+ morning_low_per_date = df_morning.groupby("date_only")["low"].min()
151
+ morning_high_per_date = df_morning.groupby("date_only")["high"].max()
152
+
153
+ df_filtered = df[df["time"].isin(required_times)].copy()
154
+ pivot_close = df_filtered.pivot(index="date_only", columns="time", values="close")
155
+ pivot_high = df_filtered.pivot(index="date_only", columns="time", values="high")
156
+ pivot_low = df_filtered.pivot(index="date_only", columns="time", values="low")
157
+ pivot_vol = df_filtered.pivot(index="date_only", columns="time", values="volume")
158
+
159
+ time_0930 = pd.to_datetime("09:30").time()
160
+ time_1510 = pd.to_datetime("15:10").time()
161
+
162
+ if time_0930 not in pivot_close.columns:
163
+ return None, None, None
164
+
165
+ pivot_close = pivot_close.dropna(subset=[time_0930])
166
+ valid_dates = pivot_close.index
167
+ times_15m = pd.date_range("09:15", "09:30", freq="min").time
168
+
169
+ feature_dicts = []
170
+ metadata = {}
171
+
172
+ for date in valid_dates:
173
+ f = {}
174
+ c_series = _safe_fill(pivot_close.loc[date, times_15m].values.astype(float))
175
+ v_series = pd.Series(pivot_vol.loc[date, times_15m].values.astype(float)).fillna(0).values
176
+ c_ref = c_series[-1]
177
+
178
+ for i, t in enumerate(times_15m):
179
+ f[f"ret_c_{i}"] = (c_series[i] / (c_ref + 1e-8)) - 1.0
180
+ f[f"raw_vol_{i}"] = v_series[i]
181
+ feature_dicts.append(f)
182
+
183
+ metadata[date] = {
184
+ "c_0930": c_ref,
185
+ "h_0930": float(pivot_high.loc[date, time_0930]) if time_0930 in pivot_high.columns else c_ref,
186
+ "l_0930": float(pivot_low.loc[date, time_0930]) if time_0930 in pivot_low.columns else c_ref,
187
+ "v_0930": float(pivot_vol.loc[date, time_0930]) if time_0930 in pivot_vol.columns else 0,
188
+ "c_1510": float(pivot_close.loc[date, time_1510]) if time_1510 in pivot_close.columns else c_ref,
189
+ "h_1510": float(pivot_high.loc[date, time_1510]) if time_1510 in pivot_high.columns else c_ref,
190
+ "l_1510": float(pivot_low.loc[date, time_1510]) if time_1510 in pivot_low.columns else c_ref,
191
+ "dip_low": float(morning_low_per_date.get(date, c_ref)),
192
+ "peak_high": float(morning_high_per_date.get(date, c_ref)),
193
+ }
194
+
195
+ X = pd.DataFrame(feature_dicts, index=valid_dates).fillna(0)
196
+
197
+ if time_1510 in pivot_close.columns:
198
+ target = (pivot_close[time_1510] > pivot_close[time_0930]).astype(int)
199
+ else:
200
+ target = pd.Series(0, index=valid_dates)
201
+
202
+ return X, target, metadata
core/groww.py ADDED
@@ -0,0 +1,112 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Groww charting API client.
3
+
4
+ Fetches 1-minute OHLCV candle data for NSE CASH segment tickers.
5
+ Handles:
6
+ - Retry with exponential backoff (3 attempts)
7
+ - None / missing values in candle arrays
8
+ - Cumulative volume -> per-candle volume conversion
9
+ """
10
+
11
+ import time
12
+ import logging
13
+ import traceback
14
+ from datetime import datetime
15
+
16
+ import numpy as np
17
+ import pandas as pd
18
+ import requests
19
+
20
+ logger = logging.getLogger("live_trader")
21
+
22
+ GROWW_HEADERS = {
23
+ "User-Agent": (
24
+ "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
25
+ "(KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
26
+ ),
27
+ "Accept": "application/json",
28
+ }
29
+
30
+
31
+ def fetch_groww_candles(ticker, days=5, max_retries=3):
32
+ """
33
+ Fetch 1-min OHLCV from Groww for the last *days* calendar days.
34
+
35
+ Returns a DataFrame [open, high, low, close, volume] with DateTimeIndex,
36
+ or None on complete failure.
37
+ """
38
+ end_ts = int(time.time() * 1000)
39
+ start_ts = end_ts - (days * 24 * 3600 * 1000)
40
+
41
+ url = (
42
+ f"https://groww.in/v1/api/charting_service/v2/chart/exchange/NSE"
43
+ f"/segment/CASH/{ticker}"
44
+ f"?endTimeInMillis={end_ts}"
45
+ f"&intervalInMinutes=1"
46
+ f"&startTimeInMillis={start_ts}"
47
+ )
48
+
49
+ for attempt in range(1, max_retries + 1):
50
+ try:
51
+ resp = requests.get(url, headers=GROWW_HEADERS, timeout=15)
52
+ resp.raise_for_status()
53
+ data = resp.json()
54
+
55
+ if "candles" not in data or not data["candles"]:
56
+ logger.warning(f"[{ticker}] No candles in API response (attempt {attempt})")
57
+ if attempt < max_retries:
58
+ time.sleep(2 * attempt)
59
+ continue
60
+ return None
61
+
62
+ rows = []
63
+ for c in data["candles"]:
64
+ # Skip candles with None / missing OHLCV values
65
+ if c[1] is None or c[2] is None or c[3] is None or c[4] is None or c[5] is None:
66
+ continue
67
+ try:
68
+ dt = datetime.fromtimestamp(c[0])
69
+ rows.append({
70
+ "date": dt,
71
+ "open": float(c[1]),
72
+ "high": float(c[2]),
73
+ "low": float(c[3]),
74
+ "close": float(c[4]),
75
+ "cum_vol": float(c[5]),
76
+ })
77
+ except (TypeError, ValueError):
78
+ continue
79
+
80
+ if not rows:
81
+ logger.warning(f"[{ticker}] All candles had None values (attempt {attempt})")
82
+ if attempt < max_retries:
83
+ time.sleep(2 * attempt)
84
+ continue
85
+ return None
86
+
87
+ df = pd.DataFrame(rows)
88
+ df.set_index("date", inplace=True)
89
+ df.sort_index(inplace=True)
90
+
91
+ # Groww volume is cumulative per day -> difference it
92
+ df["date_only"] = df.index.date
93
+ df["volume"] = df.groupby("date_only")["cum_vol"].diff().fillna(df["cum_vol"])
94
+ df["volume"] = np.where(df["volume"] < 0, df["cum_vol"], df["volume"])
95
+ df.drop(columns=["cum_vol", "date_only"], inplace=True)
96
+
97
+ logger.info(f"[{ticker}] Fetched {len(df)} candles "
98
+ f"({df.index.min()} -> {df.index.max()})")
99
+ return df
100
+
101
+ except requests.exceptions.RequestException as e:
102
+ logger.error(f"[{ticker}] API error attempt {attempt}/{max_retries}: {e}")
103
+ if attempt < max_retries:
104
+ time.sleep(3 * attempt)
105
+
106
+ except Exception as e:
107
+ logger.error(f"[{ticker}] Unexpected error attempt {attempt}/{max_retries}: {e}")
108
+ logger.debug(traceback.format_exc())
109
+ if attempt < max_retries:
110
+ time.sleep(3 * attempt)
111
+
112
+ return None
core/models.py ADDED
@@ -0,0 +1,117 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Model construction and training.
3
+
4
+ build_pipeline_map() -> dict of {ticker: (feature_type, fresh_model_clone)}
5
+ train_models() -> dict of {ticker: (feature_type, fitted_model)}
6
+ """
7
+
8
+ import pandas as pd
9
+ from sklearn.ensemble import (
10
+ RandomForestClassifier,
11
+ HistGradientBoostingClassifier,
12
+ VotingClassifier,
13
+ )
14
+ from sklearn.linear_model import LogisticRegression
15
+ from sklearn.preprocessing import StandardScaler
16
+ from sklearn.pipeline import Pipeline
17
+ from sklearn.feature_selection import SelectKBest, f_classif
18
+ from sklearn.base import clone
19
+
20
+ from core.config import TICKERS, DATA_DIR, PIPELINE_MAP
21
+ from core.features import extract_semantic_features, extract_sequential_features
22
+
23
+
24
+ # ── Base model templates ─────────────────────────────────────────────────────
25
+
26
+ _RF = RandomForestClassifier(
27
+ random_state=42, n_estimators=300, max_depth=8,
28
+ min_samples_leaf=5, n_jobs=-1,
29
+ )
30
+ _GBM = HistGradientBoostingClassifier(
31
+ random_state=42, max_iter=300, l2_regularization=1.0, max_depth=8,
32
+ )
33
+ _ENSEMBLE = VotingClassifier(
34
+ estimators=[("rf", _RF), ("gbm", _GBM)], voting="soft",
35
+ )
36
+ _LR_PIPELINE = Pipeline([
37
+ ("scaler", StandardScaler()),
38
+ ("lr", LogisticRegression(C=0.1, max_iter=1000)),
39
+ ])
40
+ _KBEST15_LR = Pipeline([
41
+ ("scaler", StandardScaler()),
42
+ ("kbest", SelectKBest(f_classif, k=15)),
43
+ ("lr", LogisticRegression(C=0.1, max_iter=1000)),
44
+ ])
45
+
46
+ _MODEL_TEMPLATES = {
47
+ "ensemble": _ENSEMBLE,
48
+ "lr_pipeline": _LR_PIPELINE,
49
+ "kbest15_lr": _KBEST15_LR,
50
+ }
51
+
52
+
53
+ # ── Public API ───────────────────────────────────────────────────────────────
54
+
55
+ def build_pipeline_map():
56
+ """
57
+ Return a dict of {ticker: (feature_type, fresh_model_clone)}.
58
+ Uses PIPELINE_MAP from config to look up the architecture per ticker.
59
+ """
60
+ result = {}
61
+ for ticker in TICKERS:
62
+ feat_type, model_key = PIPELINE_MAP[ticker]
63
+ result[ticker] = (feat_type, clone(_MODEL_TEMPLATES[model_key]))
64
+ return result
65
+
66
+
67
+ def train_models(log_fn=None):
68
+ """
69
+ Load parquet data, extract features, and train all ticker models.
70
+
71
+ Parameters
72
+ ----------
73
+ log_fn : callable(str), optional
74
+ Logging function (e.g. logger.info). Falls back to print.
75
+
76
+ Returns
77
+ -------
78
+ dict { ticker: (feature_type, fitted_model) }
79
+ """
80
+ if log_fn is None:
81
+ log_fn = print
82
+
83
+ pipeline_map = build_pipeline_map()
84
+ models = {}
85
+
86
+ for ticker in TICKERS:
87
+ fpath = DATA_DIR / f"{ticker}_minute.parquet"
88
+ if not fpath.exists():
89
+ log_fn(f"[{ticker}] Parquet file not found: {fpath}")
90
+ continue
91
+
92
+ df = pd.read_parquet(fpath)
93
+ df["date"] = pd.to_datetime(df["date"])
94
+ df.set_index("date", inplace=True)
95
+ df.sort_index(inplace=True)
96
+
97
+ # Keep at most 300 trading days
98
+ unique_days = df.index.normalize().unique()
99
+ if len(unique_days) > 300:
100
+ df = df[df.index.normalize().isin(unique_days[-300:])]
101
+
102
+ feat_type, clf = pipeline_map[ticker]
103
+
104
+ if feat_type == "semantic":
105
+ X, y, _ = extract_semantic_features(df)
106
+ else:
107
+ X, y, _ = extract_sequential_features(df)
108
+
109
+ if X is None or X.empty:
110
+ log_fn(f"[{ticker}] Feature extraction returned empty!")
111
+ continue
112
+
113
+ clf.fit(X, y)
114
+ models[ticker] = (feat_type, clf)
115
+ log_fn(f"[{ticker}] Model trained ({feat_type}) | {len(X)} samples")
116
+
117
+ return models
core/taxes.py ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Tax, brokerage, and slippage calculator for Indian equity intraday trades.
3
+ Covers: brokerage (flat Rs 20), STT, exchange txn charge, GST, SEBI fee, stamp duty.
4
+ """
5
+
6
+
7
+ def calculate_taxes_and_slippage(
8
+ price_0930, price_1510, qty,
9
+ high_0930, low_0930, high_1510, low_1510,
10
+ is_short,
11
+ ):
12
+ """
13
+ Compute net PnL after realistic slippage and all Indian regulatory charges.
14
+
15
+ Slippage model: 10% of the 1-min candle's (high - low) range,
16
+ applied as an adverse fill on both entry and exit.
17
+
18
+ Returns
19
+ -------
20
+ (net_pnl, total_taxes, exec_buy_price, exec_sell_price)
21
+ """
22
+ slip_0930 = (high_0930 - low_0930) * 0.10
23
+ slip_1510 = (high_1510 - low_1510) * 0.10
24
+
25
+ if not is_short:
26
+ # LONG: Buy at 09:30 (ask penalty), Sell at 15:10 (bid penalty)
27
+ actual_buy_price = price_0930 + slip_0930
28
+ actual_sell_price = price_1510 - slip_1510
29
+ else:
30
+ # SHORT: Sell at 09:30 (bid penalty), Buy-to-cover at 15:10 (ask penalty)
31
+ actual_sell_price = price_0930 - slip_0930
32
+ actual_buy_price = price_1510 + slip_1510
33
+
34
+ buy_turnover = actual_buy_price * qty
35
+ sell_turnover = actual_sell_price * qty
36
+ total_turnover = buy_turnover + sell_turnover
37
+
38
+ brokerage = 20.0
39
+ stt = sell_turnover * 0.00025
40
+ exc_txn_charge = total_turnover * 0.0000325
41
+ gst = (brokerage + exc_txn_charge) * 0.18
42
+ sebi_fee = total_turnover * 0.000001
43
+ stamp_duty = buy_turnover * 0.00003
44
+
45
+ total_taxes = brokerage + stt + exc_txn_charge + gst + sebi_fee + stamp_duty
46
+
47
+ gross_pnl = (actual_sell_price - actual_buy_price) * qty
48
+ net_pnl = gross_pnl - total_taxes
49
+
50
+ return net_pnl, total_taxes, actual_buy_price, actual_sell_price
data/live_trades.json ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "starting_capital": 3692.0,
3
+ "leverage": 5.0,
4
+ "last_updated": "2026-06-19T17:26:58.267583+05:30",
5
+ "trades": [
6
+ {
7
+ "date": "2026-06-19",
8
+ "ticker": "POWERGRID",
9
+ "direction": "LONG",
10
+ "confidence": 0.7291,
11
+ "entry_price": 289.6,
12
+ "shares": 63,
13
+ "capital_before": 3692.0,
14
+ "buying_power": 18460.0,
15
+ "liquidity_capped": false,
16
+ "candle_volume": 7916,
17
+ "signal_time": "2026-06-19T17:26:58.267583+05:30",
18
+ "net_pnl": null,
19
+ "exit_price": null,
20
+ "status": "OPEN",
21
+ "all_predictions": {
22
+ "INFY": {
23
+ "prob_up": 0.5328,
24
+ "prob_down": 0.4672
25
+ },
26
+ "ASIANPAINT": {
27
+ "prob_up": 0.4417,
28
+ "prob_down": 0.5583
29
+ },
30
+ "TECHM": {
31
+ "prob_up": 0.529,
32
+ "prob_down": 0.471
33
+ },
34
+ "POWERGRID": {
35
+ "prob_up": 0.7291,
36
+ "prob_down": 0.2709
37
+ },
38
+ "ONGC": {
39
+ "prob_up": 0.4045,
40
+ "prob_down": 0.5955
41
+ }
42
+ }
43
+ }
44
+ ]
45
+ }
data/minute_ohlcv/ADANIENT_minute.parquet ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:eebc57112ba3b638ac0eb0bfa0afb8ba20fc761f6f45aa91c488e383912a0810
3
+ size 14773599
data/minute_ohlcv/ADANIPORTS_minute.parquet ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:b67f6879f390678a08e49699c291d9d5f571919efbac93d698e36a33fb9cc18a
3
+ size 15238934
data/minute_ohlcv/APOLLOHOSP_minute.parquet ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:383b2cae56de9e5148107517334adbbd2a75135e6338e1253722054945aee6db
3
+ size 16979850
data/minute_ohlcv/ASIANPAINT_minute.parquet ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:091db8991ee9823b39280e0f498de5bee5da5fb6f870766c4f669538b43dc2a3
3
+ size 15802023
data/minute_ohlcv/AXISBANK_minute.parquet ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:15f276861577a02701e486b4f3e67203158a45d2187a39f374656ba17b911388
3
+ size 15441163
data/minute_ohlcv/BAJAJ-AUTO_minute.parquet ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:601e67d2b7a51e965abd48b74d4eb358492f5e5a78d4667039658af70e5a8220
3
+ size 14106851
data/minute_ohlcv/BAJAJFINSV_minute.parquet ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:03a29d080333706109ebfc5cbe4c443b768000a52e70357aaa74439e54fb7b52
3
+ size 15227892
data/minute_ohlcv/BAJFINANCE_minute.parquet ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:a396f007b0d7cea66ad3c70e1c82056d51b4ce9551ebe3055003833eaa1c837c
3
+ size 10715033
data/minute_ohlcv/BHARTIARTL_minute.parquet ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:e7d35c8f229c9dc1d7962c45161a57ef748e4aa3546652c1d33f2c92be9d90fc
3
+ size 14982789
data/minute_ohlcv/BPCL_minute.parquet ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:cacbf2ddd085066cf589e1e06afa5396830d7372e08a4a0531a884246317df9c
3
+ size 13187593
data/minute_ohlcv/BRITANNIA_minute.parquet ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:1e5d0892ed6492f785ad3fd45b46c5588f7e621894cd99dfd7440c4fe26c7359
3
+ size 17360107
data/minute_ohlcv/CIPLA_minute.parquet ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:f27a7153429f341b26463c1b87d01360f7d5d39e8f829dc485bbe450d64c2910
3
+ size 14792094
data/minute_ohlcv/COALINDIA_minute.parquet ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:bde38dda44b53363d369c08c6e0e786dc6f1c86ef9f9eca5305b6c20689aebba
3
+ size 14020728
data/minute_ohlcv/DIVISLAB_minute.parquet ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:2dc67e4779c2518d6b785d512c3c3e712fc68983c4e94735e651d9e5ba467788
3
+ size 16927541
data/minute_ohlcv/DRREDDY_minute.parquet ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:829acfff4c1ff2e33b080182da331bd94ff5b926bc7cf332ca6cc18f03bdf36e
3
+ size 14544884
data/minute_ohlcv/EICHERMOT_minute.parquet ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:14ec70cd80a92c4951630a4333ca552da7098a6b8ba7e695cbdd6b6a058eccc4
3
+ size 16372533
data/minute_ohlcv/GRASIM_minute.parquet ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:4968f3b0d7aa3540178fe1cfa3b730dd0f29f517dc8ccd043fb618e637633600
3
+ size 15487201
data/minute_ohlcv/HCLTECH_minute.parquet ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:8ffb95b06a486264d6aa3c194f74848bd337e4ed1db5a3ca13fa4c3697896cb6
3
+ size 14860521
data/minute_ohlcv/HDFCBANK_minute.parquet ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:23a13cd204544eacde2f66350dc0c757e5bba16c2614863e3f5a600c5621d1ca
3
+ size 14126028
data/minute_ohlcv/HDFCLIFE_minute.parquet ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:2e1cce52af098c3a52ab43dfdf0ffc6a35d51d2a8582e2b76438ce2128dfe55b
3
+ size 10940288
data/minute_ohlcv/HEROMOTOCO_minute.parquet ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:2e85aba15ae24c84ecab70d7c95d951137321ae46653ea59e2aebd7fb552f7ae
3
+ size 16496977
data/minute_ohlcv/HINDALCO_minute.parquet ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:e2ef7911d15de19463ab781a8d99ef8bb8cffca5ea84966a74bfa4f6cd0e5217
3
+ size 14811915
data/minute_ohlcv/HINDUNILVR_minute.parquet ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:d23ce684444fa3fb77f0728322f095333046cfeb41ce04d24fe3e11004bfb04a
3
+ size 15418103
data/minute_ohlcv/ICICIBANK_minute.parquet ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:76586d7192f781323d5f2247be3138b8f68b6836f59b1e250d8c54ad4fb772cc
3
+ size 16701861
data/minute_ohlcv/INDUSINDBK_minute.parquet ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:a1b276308d798525dc310eb1c0761b72492feecf199ff1cc0ee2c655efe6a70f
3
+ size 15676926
data/minute_ohlcv/INFY_minute.parquet ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:a3ff8af67ff82f0fb8d0feebee6e9ad69198112623e0017bb4f526e5761fbc3f
3
+ size 15787029
data/minute_ohlcv/ITC_minute.parquet ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:4549e21d5b011b39303c1deaebc41d2095f6a54b789de59d3019cb7dafe18c81
3
+ size 14482090
data/minute_ohlcv/JSWSTEEL_minute.parquet ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:abb7ac6787da7e99e28acb1d0e3ac73987cc4ddd2b62f34381354f23f0411cff
3
+ size 15132654
data/minute_ohlcv/KOTAKBANK_minute.parquet ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:8e8714261774b11205a22bfa52c5eea47a15dbf43989e8ddaa172356e96e4187
3
+ size 12401933
data/minute_ohlcv/LTIM_minute.parquet ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:c58a67f3d9e2aff5aff191fed63f05f405e01a85290b9ba6371d13eda18c4bf3
3
+ size 14677815
data/minute_ohlcv/LT_minute.parquet ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:a1479bc457abdcd5ae385f15ea0139b88a11e89026f6d89ff3bb467049df6dca
3
+ size 16306243
data/minute_ohlcv/MARUTI_minute.parquet ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:72d247e8eb660cd8807ca5bf123d5cb29405811d973eda9595981032c15bf9d5
3
+ size 18866904
data/minute_ohlcv/MM_minute.parquet ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:6cbfa7c3ba868bbff6ef6b7143f9f3c2573c8e25b742cf899121095be9829c8a
3
+ size 15397098
data/minute_ohlcv/NESTLEIND_minute.parquet ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:e7fa10b93a3d177f38784b59744ef0c610dc4de681f0818424fecb7a73722a66
3
+ size 13168657
data/minute_ohlcv/NTPC_minute.parquet ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:269f3bcf9e9cecfc7455b72d082639d57cad7d2b9c5c02c8a36f5c03aa53b85f
3
+ size 13715104
data/minute_ohlcv/ONGC_minute.parquet ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:e55660ed66362851e0350f4bd3b217eabd5fc31d092a2bd22515c077b3cd7f99
3
+ size 13962049