Update app.py
Browse files
app.py
CHANGED
|
@@ -58,9 +58,9 @@ def get_dates():
|
|
| 58 |
|
| 59 |
@app.get("/api/roots")
|
| 60 |
def get_roots(date: str):
|
| 61 |
-
"""Fetch roots available for a specific date."""
|
| 62 |
start, end = f"{date}T00:00:00", f"{date}T23:59:59"
|
| 63 |
-
data = sb_get(f"/history_buckets_fyers?select=root&minute=gte.{start}&minute=lte.{end}")
|
| 64 |
roots = set()
|
| 65 |
for row in data:
|
| 66 |
if row.get('root'):
|
|
@@ -72,7 +72,7 @@ def get_auto_config(date: str, root: str):
|
|
| 72 |
"""Smart helper for defaults (Current/Next expiry)."""
|
| 73 |
root = root.upper()
|
| 74 |
start, end = f"{date}T00:00:00", f"{date}T23:59:59"
|
| 75 |
-
data = sb_get(f"/history_buckets_fyers?select=expiry,data&root=eq.{root}&expiry=neq.MARKET&minute=gte.{start}&minute=lte.{end}&limit=
|
| 76 |
|
| 77 |
expiry_map = {}
|
| 78 |
for row in data:
|
|
@@ -112,19 +112,19 @@ def get_auto_config(date: str, root: str):
|
|
| 112 |
|
| 113 |
@app.get("/api/expiries")
|
| 114 |
def get_expiries(date: str, root: str):
|
| 115 |
-
"""Fetch distinct expiries."""
|
| 116 |
root = root.upper()
|
| 117 |
start, end = f"{date}T00:00:00", f"{date}T23:59:59"
|
| 118 |
-
data = sb_get(f"/history_buckets_fyers?select=expiry&root=eq.{root}&minute=gte.{start}&minute=lte.{end}")
|
| 119 |
exps = set(row['expiry'] for row in data if row.get('expiry'))
|
| 120 |
return JSONResponse(sorted(list(exps)))
|
| 121 |
|
| 122 |
@app.get("/api/instruments")
|
| 123 |
def get_instruments(date: str, root: str, expiry: str):
|
| 124 |
-
"""Fetch instruments and segregate into spot/future vs options.
|
| 125 |
root = root.upper()
|
| 126 |
start, end = f"{date}T00:00:00", f"{date}T23:59:59"
|
| 127 |
-
data = sb_get(f"/history_buckets_fyers?select=data&root=eq.{root}&expiry=eq.{expiry}&minute=gte.{start}&minute=lte.{end}&limit=
|
| 128 |
instruments = set()
|
| 129 |
for row in data:
|
| 130 |
keys = row.get('data', {}).keys()
|
|
@@ -224,7 +224,7 @@ def fetch_series(
|
|
| 224 |
k_data = data_dict[k]
|
| 225 |
bv = k_data.get('b', [0]*6)
|
| 226 |
sv = k_data.get('s', [0]*6)
|
| 227 |
-
vv = k_data.get('v',
|
| 228 |
ov = k_data.get('o', [0]*6)
|
| 229 |
|
| 230 |
b_val = float(bv[i]) if i < len(bv) and bv[i] else 0.0
|
|
@@ -259,7 +259,7 @@ def fetch_series(
|
|
| 259 |
b_arr = inst_data.get('b',[]) or[]
|
| 260 |
s_arr = inst_data.get('s', []) or[]
|
| 261 |
v_arr = inst_data.get('v', []) or[]
|
| 262 |
-
o_arr = inst_data.get('o',
|
| 263 |
|
| 264 |
for i in range(6):
|
| 265 |
if i < len(p_arr) and p_arr[i] is not None:
|
|
@@ -663,7 +663,7 @@ const CustomDD = {
|
|
| 663 |
document.querySelectorAll('.custom-dd').forEach(el => el.style.display = 'none');
|
| 664 |
const inp = document.getElementById(id);
|
| 665 |
inp.select();
|
| 666 |
-
this.render(id, ''); //
|
| 667 |
document.getElementById(`dd-${id}`).style.display = 'block';
|
| 668 |
},
|
| 669 |
filter(id) {
|
|
@@ -704,11 +704,16 @@ const CustomDD = {
|
|
| 704 |
const App = {
|
| 705 |
state: { date: null, mode: 'LIVE', columns: 3, layout: [[],[],[]], charts: {}, refreshRate: 15 },
|
| 706 |
presets: {
|
| 707 |
-
"
|
| 708 |
{ formula: '$P', color1: '#2f81f7', cond: 'none', label: 'Price', axis: 'left' },
|
| 709 |
{ formula: '$B', color1: '#238636', cond: 'none', label: 'Buy', axis: 'right' },
|
| 710 |
{ formula: '$S', color1: '#da3633', cond: 'none', label: 'Sell', axis: 'right' }
|
| 711 |
],
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 712 |
"Model 2":[
|
| 713 |
{ formula: '$P', color1: '#2f81f7', cond: 'none', label: 'Price', axis: 'left' },
|
| 714 |
{ formula: '$CB + $PS - ($PB + $CS)', color1: '#238636', color2: '#da3633', cond: '>', thresh: 0, label: 'Overall', axis: 'right' }
|
|
@@ -1083,7 +1088,7 @@ const Config = {
|
|
| 1083 |
|
| 1084 |
this.updateInfoTooltip(mode);
|
| 1085 |
this.updatePresetsDropdown();
|
| 1086 |
-
this.loadPreset(mode === 'advanced' ? "Model
|
| 1087 |
},
|
| 1088 |
|
| 1089 |
updateInfoTooltip(mode) {
|
|
@@ -1125,7 +1130,7 @@ const Config = {
|
|
| 1125 |
|
| 1126 |
deletePreset() {
|
| 1127 |
const name = document.getElementById('cfgPresetsDropdown').value;
|
| 1128 |
-
if(name.startsWith('Model 1') || name.startsWith('Model 2')) return alert("Cannot delete default models.");
|
| 1129 |
if(confirm(`Delete model '${name}'?`)) {
|
| 1130 |
delete App.presets[name];
|
| 1131 |
localStorage.setItem('dc_pro_v3_presets', JSON.stringify(App.presets));
|
|
@@ -1172,7 +1177,7 @@ const Config = {
|
|
| 1172 |
if (cfg.series && cfg.series.length > 0) {
|
| 1173 |
this.renderSeries(cfg.series);
|
| 1174 |
} else {
|
| 1175 |
-
this.loadPreset(this.currentMode === 'advanced' ? "Model
|
| 1176 |
}
|
| 1177 |
|
| 1178 |
document.getElementById('cfgRoot').value = cfg.root || '';
|
|
@@ -1196,7 +1201,7 @@ const Config = {
|
|
| 1196 |
document.getElementById('cfgRefresh').value = App.state.refreshRate || 15;
|
| 1197 |
|
| 1198 |
this.updatePresetsDropdown();
|
| 1199 |
-
this.loadPreset("
|
| 1200 |
},
|
| 1201 |
|
| 1202 |
close() { document.getElementById('configModal').style.display = 'none'; },
|
|
|
|
| 58 |
|
| 59 |
@app.get("/api/roots")
|
| 60 |
def get_roots(date: str):
|
| 61 |
+
"""Fetch ALL roots available for a specific date."""
|
| 62 |
start, end = f"{date}T00:00:00", f"{date}T23:59:59"
|
| 63 |
+
data = sb_get(f"/history_buckets_fyers?select=root&minute=gte.{start}&minute=lte.{end}&limit=50000")
|
| 64 |
roots = set()
|
| 65 |
for row in data:
|
| 66 |
if row.get('root'):
|
|
|
|
| 72 |
"""Smart helper for defaults (Current/Next expiry)."""
|
| 73 |
root = root.upper()
|
| 74 |
start, end = f"{date}T00:00:00", f"{date}T23:59:59"
|
| 75 |
+
data = sb_get(f"/history_buckets_fyers?select=expiry,data&root=eq.{root}&expiry=neq.MARKET&minute=gte.{start}&minute=lte.{end}&limit=200")
|
| 76 |
|
| 77 |
expiry_map = {}
|
| 78 |
for row in data:
|
|
|
|
| 112 |
|
| 113 |
@app.get("/api/expiries")
|
| 114 |
def get_expiries(date: str, root: str):
|
| 115 |
+
"""Fetch ALL distinct expiries."""
|
| 116 |
root = root.upper()
|
| 117 |
start, end = f"{date}T00:00:00", f"{date}T23:59:59"
|
| 118 |
+
data = sb_get(f"/history_buckets_fyers?select=expiry&root=eq.{root}&minute=gte.{start}&minute=lte.{end}&limit=50000")
|
| 119 |
exps = set(row['expiry'] for row in data if row.get('expiry'))
|
| 120 |
return JSONResponse(sorted(list(exps)))
|
| 121 |
|
| 122 |
@app.get("/api/instruments")
|
| 123 |
def get_instruments(date: str, root: str, expiry: str):
|
| 124 |
+
"""Fetch instruments and segregate into spot/future vs options."""
|
| 125 |
root = root.upper()
|
| 126 |
start, end = f"{date}T00:00:00", f"{date}T23:59:59"
|
| 127 |
+
data = sb_get(f"/history_buckets_fyers?select=data&root=eq.{root}&expiry=eq.{expiry}&minute=gte.{start}&minute=lte.{end}&limit=100")
|
| 128 |
instruments = set()
|
| 129 |
for row in data:
|
| 130 |
keys = row.get('data', {}).keys()
|
|
|
|
| 224 |
k_data = data_dict[k]
|
| 225 |
bv = k_data.get('b', [0]*6)
|
| 226 |
sv = k_data.get('s', [0]*6)
|
| 227 |
+
vv = k_data.get('v',[0]*6)
|
| 228 |
ov = k_data.get('o', [0]*6)
|
| 229 |
|
| 230 |
b_val = float(bv[i]) if i < len(bv) and bv[i] else 0.0
|
|
|
|
| 259 |
b_arr = inst_data.get('b',[]) or[]
|
| 260 |
s_arr = inst_data.get('s', []) or[]
|
| 261 |
v_arr = inst_data.get('v', []) or[]
|
| 262 |
+
o_arr = inst_data.get('o',[]) or[]
|
| 263 |
|
| 264 |
for i in range(6):
|
| 265 |
if i < len(p_arr) and p_arr[i] is not None:
|
|
|
|
| 663 |
document.querySelectorAll('.custom-dd').forEach(el => el.style.display = 'none');
|
| 664 |
const inp = document.getElementById(id);
|
| 665 |
inp.select();
|
| 666 |
+
this.render(id, ''); // Empty string ignores typed text and shows all options!
|
| 667 |
document.getElementById(`dd-${id}`).style.display = 'block';
|
| 668 |
},
|
| 669 |
filter(id) {
|
|
|
|
| 704 |
const App = {
|
| 705 |
state: { date: null, mode: 'LIVE', columns: 3, layout: [[],[],[]], charts: {}, refreshRate: 15 },
|
| 706 |
presets: {
|
| 707 |
+
"Standard (Normal Mode)":[
|
| 708 |
{ formula: '$P', color1: '#2f81f7', cond: 'none', label: 'Price', axis: 'left' },
|
| 709 |
{ formula: '$B', color1: '#238636', cond: 'none', label: 'Buy', axis: 'right' },
|
| 710 |
{ formula: '$S', color1: '#da3633', cond: 'none', label: 'Sell', axis: 'right' }
|
| 711 |
],
|
| 712 |
+
"Model 1":[
|
| 713 |
+
{ formula: '$P', color1: '#2f81f7', cond: 'none', label: 'Price', axis: 'left' },
|
| 714 |
+
{ formula: '$CB + $PS', color1: '#238636', cond: 'none', label: 'Buy Prs', axis: 'right' },
|
| 715 |
+
{ formula: '$CS + $PB', color1: '#da3633', cond: 'none', label: 'Sell Prs', axis: 'right' }
|
| 716 |
+
],
|
| 717 |
"Model 2":[
|
| 718 |
{ formula: '$P', color1: '#2f81f7', cond: 'none', label: 'Price', axis: 'left' },
|
| 719 |
{ formula: '$CB + $PS - ($PB + $CS)', color1: '#238636', color2: '#da3633', cond: '>', thresh: 0, label: 'Overall', axis: 'right' }
|
|
|
|
| 1088 |
|
| 1089 |
this.updateInfoTooltip(mode);
|
| 1090 |
this.updatePresetsDropdown();
|
| 1091 |
+
this.loadPreset(mode === 'advanced' ? "Model 1" : "Standard (Normal Mode)");
|
| 1092 |
},
|
| 1093 |
|
| 1094 |
updateInfoTooltip(mode) {
|
|
|
|
| 1130 |
|
| 1131 |
deletePreset() {
|
| 1132 |
const name = document.getElementById('cfgPresetsDropdown').value;
|
| 1133 |
+
if(name.startsWith('Model 1') || name.startsWith('Model 2') || name.startsWith('Standard')) return alert("Cannot delete default models.");
|
| 1134 |
if(confirm(`Delete model '${name}'?`)) {
|
| 1135 |
delete App.presets[name];
|
| 1136 |
localStorage.setItem('dc_pro_v3_presets', JSON.stringify(App.presets));
|
|
|
|
| 1177 |
if (cfg.series && cfg.series.length > 0) {
|
| 1178 |
this.renderSeries(cfg.series);
|
| 1179 |
} else {
|
| 1180 |
+
this.loadPreset(this.currentMode === 'advanced' ? "Model 1" : "Standard (Normal Mode)");
|
| 1181 |
}
|
| 1182 |
|
| 1183 |
document.getElementById('cfgRoot').value = cfg.root || '';
|
|
|
|
| 1201 |
document.getElementById('cfgRefresh').value = App.state.refreshRate || 15;
|
| 1202 |
|
| 1203 |
this.updatePresetsDropdown();
|
| 1204 |
+
this.loadPreset("Standard (Normal Mode)");
|
| 1205 |
},
|
| 1206 |
|
| 1207 |
close() { document.getElementById('configModal').style.display = 'none'; },
|