topsecrettraders commited on
Commit
1947cab
·
verified ·
1 Parent(s): bdbf674

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +87 -4
app.py CHANGED
@@ -501,6 +501,11 @@ HTML_TEMPLATE = """
501
  .sec-pill { padding: 2px 5px; font-size: 10px; cursor: pointer; border-radius: 2px; color: #666; font-family:'JetBrains Mono'; }
502
  .sec-pill:hover { background: #ddd; color: #000; }
503
  .sec-pill.active { background: var(--accent); color: white; font-weight: bold; }
 
 
 
 
 
504
 
505
  .grid-layout { display: flex; height: calc(100vh - 60px); }
506
 
@@ -932,15 +937,93 @@ HTML_TEMPLATE = """
932
  document.getElementById('loader').style.display = 'none';
933
  }
934
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
935
  function renderSecondBar() {
936
  const bar = document.getElementById('secBar');
937
- bar.innerHTML = CACHED_TIMELINE.map((item, idx) => `
938
- <div class="sec-pill ${idx===0?'active':''}"
 
 
 
 
 
939
  onclick="selectSnapshot(${idx})"
940
- id="pill-${idx}">
 
941
  :${item.s}
942
  </div>
943
- `).join('');
944
  }
945
 
946
  function selectSnapshot(idx) {
 
501
  .sec-pill { padding: 2px 5px; font-size: 10px; cursor: pointer; border-radius: 2px; color: #666; font-family:'JetBrains Mono'; }
502
  .sec-pill:hover { background: #ddd; color: #000; }
503
  .sec-pill.active { background: var(--accent); color: white; font-weight: bold; }
504
+
505
+ /* CORRUPTED DATA INDICATOR */
506
+ .sec-pill.bad { background: #ff5252; color: white; opacity: 0.9; }
507
+ .sec-pill.bad:hover { background: #d50000; }
508
+ .sec-pill.bad.active { background: #b71c1c; border: 1px solid #fff; }
509
 
510
  .grid-layout { display: flex; height: calc(100vh - 60px); }
511
 
 
937
  document.getElementById('loader').style.display = 'none';
938
  }
939
 
940
+ // --- VALIDATION LOGIC FOR HISTORICAL DATA ---
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 and check if data exists
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')) {
950
+ if(data[sym].ltp > 0) refPrice = data[sym].ltp;
951
+ }
952
+ // Fallback to Future if Spot not found or is 0
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
+ // CRITERIA 2: Validate ATM ± Range Data (Zero Qty Check)
964
+ if(hasOptions) {
965
+ // Extract valid strikes from symbol keys
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
+ if(strikes.length > 0) {
979
+ // Find ATM Strike based on Ref Price
980
+ strikes.sort((a,b) => a.k - b.k);
981
+ let closest = strikes.reduce((prev, curr) =>
982
+ Math.abs(curr.k - refPrice) < Math.abs(prev.k - refPrice) ? curr : prev
983
+ );
984
+
985
+ // Get unique strikes to determine index range
986
+ let uniqKs = [...new Set(strikes.map(i => i.k))].sort((a,b)=>a-b);
987
+ let atmIndex = uniqKs.indexOf(closest.k);
988
+
989
+ // Define Range: ATM ± 5 strikes
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
+ return true; // Data passed checks
1010
+ }
1011
+
1012
  function renderSecondBar() {
1013
  const bar = document.getElementById('secBar');
1014
+ bar.innerHTML = CACHED_TIMELINE.map((item, idx) => {
1015
+ // Run validation on the data packet ('d')
1016
+ const isValid = validateSnapshot(item.d);
1017
+ const statusClass = isValid ? '' : 'bad';
1018
+
1019
+ return `
1020
+ <div class="sec-pill ${idx===0?'active':''} ${statusClass}"
1021
  onclick="selectSnapshot(${idx})"
1022
+ id="pill-${idx}"
1023
+ title="${isValid ? 'Data OK' : 'Data Inefficient (Zero Qty or Missing Ref)'}">
1024
  :${item.s}
1025
  </div>
1026
+ `}).join('');
1027
  }
1028
 
1029
  function selectSnapshot(idx) {