File size: 5,624 Bytes
3f54611 6c0386c dd7bee7 3081989 97cd7bd 06ebc06 b5a0b36 bb2645d b5a0b36 088f763 cf177c3 9b86c34 3081989 97848e1 73b65e7 b5a0b36 c332c65 73b65e7 b5a0b36 9b86c34 97848e1 8edc019 3081989 97848e1 3081989 97848e1 3081989 8edc019 3081989 9b86c34 3081989 9b86c34 11f39a0 06ebc06 bb2645d 9b86c34 |
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 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 |
import yfinance as yf
import pandas as pd
import io
import requests
from datetime import datetime, timedelta
from ta_indi_pat import talib_df # use the combined talib_df function
from common import html_card, wrap_html
# -----------------------------
# Global Variables
# -----------------------------
nse_del_key_map = {
'Symbol': "Symbol", 'Series': "Series",
'Date': 'Date', 'Prev Close': 'Preclose',
'Open Price': 'Open', 'High Price': 'High',
'Low Price': 'Low', 'Last Price': 'Last',
'Close Price': 'Close', 'Average Price': 'AvgPrice',
'Total Traded Quantity': 'Volume',
'Turnover ₹': 'Turnover', 'No. of Trades': "Trades",
'Deliverable Qty': "Delivery", '% Dly Qt to Traded Qty': "Del%"
}
# -----------------------------
# Data Fetching Functions (NSE)
# -----------------------------
def url_nse_del(symbol, start_date, end_date):
base_url = "https://www.nseindia.com/api/historicalOR/generateSecurityWiseHistoricalData"
start_date_str = start_date.strftime("%d-%m-%Y")
end_date_str = end_date.strftime("%d-%m-%Y")
url = f"{base_url}?from={start_date_str}&to={end_date_str}&symbol={symbol.split('.')[0]}&type=priceVolumeDeliverable&series=ALL&csv=true"
return url
def to_numeric_safe(series):
series = series.replace('-', 0)
series = series.fillna(0)
series = series.astype(str).str.replace(',', '')
return pd.to_numeric(series, errors='coerce').fillna(0)
def nse_del(symbol, start_date_str=None, end_date_str=None):
# Default end date is today
end_date = datetime.now()
if end_date_str:
try:
end_date = datetime.strptime(end_date_str, "%Y-%m-%d")
except ValueError:
print(f"Warning: Invalid end date format '{end_date_str}'. Using today's date.")
end_date = datetime.now()
# Default start date is one year prior to end_date
start_date = end_date - timedelta(days=365)
if start_date_str:
try:
start_date = datetime.strptime(start_date_str, "%Y-%m-%d")
except ValueError:
print(f"Warning: Invalid start date format '{start_date_str}'. Using default start date.")
start_date = end_date - timedelta(days=365)
# Ensure start_date is not after end_date
if start_date > end_date:
print("Warning: Start date is after end date. Swapping dates.")
start_date, end_date = end_date, start_date
url = url_nse_del(symbol, start_date, end_date)
headers = {
'User-Agent': 'Mozilla/5.0'
}
try:
response = requests.get(url, headers=headers)
response.raise_for_status()
if response.content:
df = pd.read_csv(io.StringIO(response.content.decode('utf-8'))).round(2)
df.columns = df.columns.str.strip()
df.rename(columns=nse_del_key_map, inplace=True)
# Capitalize the first letter of ALL column names after renaming
df.columns = [col.capitalize() for col in df.columns]
# Remove 'Symbol', 'Series', 'Avgprice', and 'Last' columns (now capitalized)
df.drop(columns=['Symbol','Series','Avgprice','Last'], errors='ignore', inplace=True)
# Convert 'Date' column to datetime objects
df['Date'] = pd.to_datetime(df['Date'], format='%d-%b-%Y').dt.strftime('%Y-%m-%d')
numeric_cols = ['Close', 'Preclose', 'Open', 'High', 'Low', 'Volume', 'Delivery', 'Turnover', 'Trades']
# Ensure numeric_cols are capitalized before checking and conversion
numeric_cols_capitalized = [col.capitalize() for col in numeric_cols]
for col in numeric_cols_capitalized:
if col in df.columns:
df[col] = to_numeric_safe(df[col])
else:
df[col] = 0
return df
except Exception as e:
print(f"Error fetching data from NSE for {symbol}: {e}")
return None
def daily(symbol,source="yfinace"):
if source=="yfinance":
df = yf.download(symbol + ".NS", period="1y", interval="1d").round(2)
if df.empty:
return html_card("Error", f"No daily data found for {symbol}")
# --- Standardize columns ---
df.columns = ["Close", "High", "Low", "Open", "Volume"]
df.reset_index(inplace=True) # make Date a column
if source=="NSE":
df=nse_del(symbol)
print("df from nse data")
return df
def fetch_daily(symbol, source,max_rows=200):
"""
Fetch daily OHLCV data, calculate TA-Lib indicators + patterns,
return a single scrollable HTML table.
"""
try:
# --- Fetch daily data ---
df=daily(symbol,source)
# --- Limit rows for display ---
df_display = df.head(max_rows)
# --- Generate combined TA-Lib DataFrame ---
combined_df = talib_df(df_display)
# --- Convert to HTML table ---
table_html = combined_df.to_html(
classes="table table-striped table-bordered",
index=False
)
# --- Wrap in scrollable div ---
scrollable_html = f"""
<div style="overflow-x:auto; overflow-y:auto; max-height:600px; border:1px solid #ccc; padding:5px;">
{table_html}
</div>
"""
# --- Wrap in card and full HTML ---
content = f"""
<h2>{symbol} - Daily Data (OHLCV + Indicators + Patterns)</h2>
{html_card("TA-Lib Data", scrollable_html)}
"""
return wrap_html(content, title=f"{symbol} Daily Data")
except Exception as e:
return html_card("Error", str(e))
|