Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -941,9 +941,8 @@ HTML_TEMPLATE = """
|
|
| 941 |
function validateSnapshot(data) {
|
| 942 |
// 1. Identify Reference Price (Spot or Future)
|
| 943 |
let refPrice = 0;
|
| 944 |
-
let hasOptions = false;
|
| 945 |
|
| 946 |
-
// Loop to find Reference
|
| 947 |
for(let sym in data) {
|
| 948 |
// Check for Spot or Index (Priority)
|
| 949 |
if(sym.includes('INDEX') || sym.endsWith('-EQ') || sym.startsWith('BSE:SENSEX')) {
|
|
@@ -953,60 +952,67 @@ HTML_TEMPLATE = """
|
|
| 953 |
else if(sym.endsWith('FUT') && refPrice === 0) {
|
| 954 |
if(data[sym].ltp > 0) refPrice = data[sym].ltp;
|
| 955 |
}
|
| 956 |
-
// Check if options exist in this packet
|
| 957 |
-
if(sym.endsWith('CE') || sym.endsWith('PE')) hasOptions = true;
|
| 958 |
}
|
| 959 |
|
| 960 |
// CRITERIA 1: Missing Reference Price (Corrupted)
|
| 961 |
if(refPrice === 0) return false;
|
| 962 |
|
| 963 |
-
//
|
| 964 |
-
|
| 965 |
-
|
| 966 |
-
let strikes = [];
|
| 967 |
-
for(let sym in data) {
|
| 968 |
-
// Regex matches Fyers symbols ending in Number+CE/PE (e.g., ...22100CE)
|
| 969 |
-
let match = sym.match(/(\d+)(CE|PE)$/);
|
| 970 |
-
if(match && match[1]) {
|
| 971 |
-
strikes.push({
|
| 972 |
-
k: parseFloat(match[1]),
|
| 973 |
-
d: data[sym]
|
| 974 |
-
});
|
| 975 |
-
}
|
| 976 |
-
}
|
| 977 |
|
| 978 |
-
|
| 979 |
-
|
| 980 |
-
|
| 981 |
-
|
| 982 |
-
|
| 983 |
-
);
|
|
|
|
| 984 |
|
| 985 |
-
|
| 986 |
-
|
| 987 |
-
let atmIndex = uniqKs.indexOf(closest.k);
|
| 988 |
|
| 989 |
-
|
| 990 |
-
let start = Math.max(0, atmIndex - 5);
|
| 991 |
-
let end = Math.min(uniqKs.length - 1, atmIndex + 5);
|
| 992 |
-
let targetKs = uniqKs.slice(start, end + 1);
|
| 993 |
-
|
| 994 |
-
// Check specific options in this range
|
| 995 |
-
for(let item of strikes) {
|
| 996 |
-
if(targetKs.includes(item.k)) {
|
| 997 |
-
let qB = item.d.totalbuyqty;
|
| 998 |
-
let qS = item.d.totalsellqty;
|
| 999 |
-
|
| 1000 |
-
// THE CHECK: If both Buy AND Sell Qty are 0 or undefined -> Data is inefficient
|
| 1001 |
-
if((!qB && !qS) || (qB === 0 && qS === 0)) {
|
| 1002 |
-
return false; // Mark as Bad
|
| 1003 |
-
}
|
| 1004 |
-
}
|
| 1005 |
-
}
|
| 1006 |
}
|
| 1007 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1008 |
|
| 1009 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1010 |
}
|
| 1011 |
|
| 1012 |
function renderSecondBar() {
|
|
@@ -1020,7 +1026,7 @@ HTML_TEMPLATE = """
|
|
| 1020 |
<div class="sec-pill ${idx===0?'active':''} ${statusClass}"
|
| 1021 |
onclick="selectSnapshot(${idx})"
|
| 1022 |
id="pill-${idx}"
|
| 1023 |
-
title="${isValid ? 'Data OK' : '
|
| 1024 |
:${item.s}
|
| 1025 |
</div>
|
| 1026 |
`}).join('');
|
|
|
|
| 941 |
function validateSnapshot(data) {
|
| 942 |
// 1. Identify Reference Price (Spot or Future)
|
| 943 |
let refPrice = 0;
|
|
|
|
| 944 |
|
| 945 |
+
// Loop to find Reference
|
| 946 |
for(let sym in data) {
|
| 947 |
// Check for Spot or Index (Priority)
|
| 948 |
if(sym.includes('INDEX') || sym.endsWith('-EQ') || sym.startsWith('BSE:SENSEX')) {
|
|
|
|
| 952 |
else if(sym.endsWith('FUT') && refPrice === 0) {
|
| 953 |
if(data[sym].ltp > 0) refPrice = data[sym].ltp;
|
| 954 |
}
|
|
|
|
|
|
|
| 955 |
}
|
| 956 |
|
| 957 |
// CRITERIA 1: Missing Reference Price (Corrupted)
|
| 958 |
if(refPrice === 0) return false;
|
| 959 |
|
| 960 |
+
// 2. Parse and Organize Data by Strike
|
| 961 |
+
let strikesMap = {}; // { 21000: { CE: obj, PE: obj } }
|
| 962 |
+
let allStrikes = [];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 963 |
|
| 964 |
+
for(let sym in data) {
|
| 965 |
+
// Regex to extract Strike + Type (e.g. ...22100CE -> 22100, CE)
|
| 966 |
+
// Handles potential decimal strikes as well
|
| 967 |
+
let match = sym.match(/(\d+(?:\.\d+)?)(CE|PE)$/);
|
| 968 |
+
if(match && match[1]) {
|
| 969 |
+
let k = parseFloat(match[1]);
|
| 970 |
+
let type = match[2]; // 'CE' or 'PE'
|
| 971 |
|
| 972 |
+
if(!strikesMap[k]) strikesMap[k] = { CE: null, PE: null };
|
| 973 |
+
strikesMap[k][type] = data[sym];
|
|
|
|
| 974 |
|
| 975 |
+
if(!allStrikes.includes(k)) allStrikes.push(k);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 976 |
}
|
| 977 |
}
|
| 978 |
+
|
| 979 |
+
if(allStrikes.length === 0) return false; // No options found
|
| 980 |
+
|
| 981 |
+
// 3. Find ATM Strike based on Ref Price
|
| 982 |
+
allStrikes.sort((a,b) => a - b);
|
| 983 |
+
let closest = allStrikes.reduce((prev, curr) =>
|
| 984 |
+
Math.abs(curr - refPrice) < Math.abs(prev - refPrice) ? curr : prev
|
| 985 |
+
);
|
| 986 |
+
let atmIdx = allStrikes.indexOf(closest);
|
| 987 |
+
|
| 988 |
+
// 4. Validate Range: ATM ± 7 Strikes
|
| 989 |
+
let start = Math.max(0, atmIdx - 7);
|
| 990 |
+
let end = Math.min(allStrikes.length - 1, atmIdx + 7);
|
| 991 |
|
| 992 |
+
// Iterate through the specific range
|
| 993 |
+
for(let i = start; i <= end; i++) {
|
| 994 |
+
let k = allStrikes[i];
|
| 995 |
+
let instruments = strikesMap[k];
|
| 996 |
+
|
| 997 |
+
// CRITERIA 2: Missing Instrument (Pair Check)
|
| 998 |
+
// If either CE or PE is completely missing from the data -> Corrupted
|
| 999 |
+
if(!instruments.CE || !instruments.PE) {
|
| 1000 |
+
return false;
|
| 1001 |
+
}
|
| 1002 |
+
|
| 1003 |
+
// CRITERIA 3: Data Quality (Zero Qty Check)
|
| 1004 |
+
// Check CE Quality
|
| 1005 |
+
let ceB = instruments.CE.totalbuyqty || 0;
|
| 1006 |
+
let ceS = instruments.CE.totalsellqty || 0;
|
| 1007 |
+
if(ceB === 0 && ceS === 0) return false;
|
| 1008 |
+
|
| 1009 |
+
// Check PE Quality
|
| 1010 |
+
let peB = instruments.PE.totalbuyqty || 0;
|
| 1011 |
+
let peS = instruments.PE.totalsellqty || 0;
|
| 1012 |
+
if(peB === 0 && peS === 0) return false;
|
| 1013 |
+
}
|
| 1014 |
+
|
| 1015 |
+
return true; // Data Passed all checks
|
| 1016 |
}
|
| 1017 |
|
| 1018 |
function renderSecondBar() {
|
|
|
|
| 1026 |
<div class="sec-pill ${idx===0?'active':''} ${statusClass}"
|
| 1027 |
onclick="selectSnapshot(${idx})"
|
| 1028 |
id="pill-${idx}"
|
| 1029 |
+
title="${isValid ? 'Data OK' : 'Inefficient Data: Missing Inst/Qty or Ref'}">
|
| 1030 |
:${item.s}
|
| 1031 |
</div>
|
| 1032 |
`}).join('');
|