File size: 4,277 Bytes
69f5fb0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
import os
import time
import requests
import pandas as pd
from datetime import datetime, date, timedelta
from zoneinfo import ZoneInfo
import pandas_market_calendars as mcal

IST = ZoneInfo("Asia/Kolkata")
DATA_FILE = os.path.join(os.path.dirname(__file__), "data", "nifty50_daily.parquet")

TICKERS = [
    'ADANIENT', 'ADANIPORTS', 'APOLLOHOSP', 'ASIANPAINT', 'AXISBANK', 'BAJAJ-AUTO', 'BAJAJFINSV', 'BAJFINANCE', 
    'BHARTIARTL', 'BPCL', 'BRITANNIA', 'CIPLA', 'COALINDIA', 'DIVISLAB', 'DRREDDY', 'EICHERMOT', 'GRASIM', 
    'HCLTECH', 'HDFCBANK', 'HDFCLIFE', 'HEROMOTOCO', 'HINDALCO', 'HINDUNILVR', 'ICICIBANK', 'INDUSINDBK', 
    'INFY', 'ITC', 'JSWSTEEL', 'KOTAKBANK', 'LT', 'M&M', 'MARUTI', 'NESTLEIND', 'NTPC', 'ONGC', 'POWERGRID', 
    'RELIANCE', 'SBILIFE', 'SBIN', 'SUNPHARMA', 'TATACONSUM', 'TATAMOTORS', 'TATASTEEL', 'TCS', 'TECHM', 
    'TITAN', 'ULTRACEMCO', 'UPL', 'WIPRO'
]

def is_trading_day(target_date: date) -> bool:
    try:
        nse = mcal.get_calendar('NSE')
        schedule = nse.schedule(start_date=target_date, end_date=target_date)
        return not schedule.empty
    except Exception as e:
        print(f"Calendar check failed: {e}")
        # Fallback: assume Monday-Friday is trading day
        return target_date.weekday() < 5

def fetch_groww_data(ticker: str, start_ts: int, end_ts: int):
    url = f"https://groww.in/v1/api/charting_service/v2/chart/exchange/NSE/segment/CASH/{ticker}?endTimeInMillis={end_ts}&intervalInMinutes=1&startTimeInMillis={start_ts}"
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)",
        "Accept": "application/json"
    }
    
    try:
        response = requests.get(url, headers=headers, timeout=10)
        if response.status_code == 200:
            data = response.json()
            if data and 'candles' in data and len(data['candles']) > 0:
                # Candles format: [timestamp, open, high, low, close, volume]
                last_candle = data['candles'][-1]
                return last_candle[4] # Close price
        return None
    except Exception as e:
        print(f"Error fetching {ticker}: {e}")
        return None

def update_daily_data():
    now = datetime.now(IST)
    today = now.date()
    
    if not is_trading_day(today):
        print(f"{today} is not a trading day. Skipping update.")
        return {"status": "skipped", "reason": "not a trading day"}
        
    if not os.path.exists(DATA_FILE):
        print(f"Data file {DATA_FILE} not found!")
        return {"status": "error", "reason": "data file missing"}
        
    # Read existing data
    df = pd.read_parquet(DATA_FILE)
    
    # Check if we already updated today
    if not df.empty and pd.to_datetime(today) in df['date'].dt.date.values:
        # We might have partial data or want to overwrite, but for safety:
        # Let's delete today's entries if they exist so we can cleanly append
        df = df[df['date'].dt.date != today]
        
    print(f"Fetching data for {today}...")
    
    # Market hours: 09:15 to 15:30 IST
    start_dt = datetime.combine(today, datetime.strptime("09:15", "%H:%M").time()).replace(tzinfo=IST)
    end_dt = datetime.combine(today, datetime.strptime("15:30", "%H:%M").time()).replace(tzinfo=IST)
    
    start_ts = int(start_dt.timestamp() * 1000)
    end_ts = int(end_dt.timestamp() * 1000)
    
    new_rows = []
    
    for ticker in TICKERS:
        close_price = fetch_groww_data(ticker, start_ts, end_ts)
        if close_price is not None:
            new_rows.append({
                'date': pd.to_datetime(today),
                'close': float(close_price),
                'ticker': ticker
            })
        time.sleep(0.5) # Rate limiting
        
    if new_rows:
        new_df = pd.DataFrame(new_rows)
        updated_df = pd.concat([df, new_df], ignore_index=True)
        updated_df.sort_values(by=['ticker', 'date'], inplace=True)
        updated_df.to_parquet(DATA_FILE)
        print(f"Successfully updated {len(new_rows)} tickers for {today}")
        return {"status": "success", "updated_count": len(new_rows)}
    else:
        print("No new data fetched.")
        return {"status": "error", "reason": "fetch failed for all tickers"}

if __name__ == "__main__":
    update_daily_data()