/* Company Stock Price — Stock Screener (live NSE quotes, API fields only) */ const SCREENER_FILTERS = ['All', 'Gainers', 'Losers', 'Unchanged']; const SORT_OPTS = [ { key: 'price', label: 'Price' }, { key: 'chg', label: 'Change %' }, { key: 'vol', label: 'Volume' }, { key: 'hi52', label: '52W High' }, { key: 'lo52', label: '52W Low' }, ]; const SCREENER_PAGE = 25; const COLS = [ { key: 'rank', label: '#', cls: 'col-rank', sortable: false }, { key: 'company', label: 'Company', cls: 'col-company', sortable: false }, { key: 'price', label: 'Price', sortable: true }, { key: 'chg', label: 'Chg %', sortable: true }, { key: 'vol', label: 'Volume', sortable: true }, { key: 'hi52', label: '52W High', sortable: true }, { key: 'lo52', label: '52W Low', sortable: true }, { key: 'action', label: '', sortable: false }, ]; const QB_FIELDS = [ { key: 'price', label: 'Price', unit: '₹', fmt: (v) => '₹' + fmt.price(v) }, { key: 'chg', label: '1-Day Change', unit: '%', fmt: (v) => fmt.pct(v) }, { key: 'vol', label: 'Volume', unit: 'sh', fmt: (v) => (v != null ? fmt.vol(v) : '—') }, { key: 'fromHi', label: '% below 52W High', unit: '%', derive: (s) => s.hi52 ? +((1 - s.price / s.hi52) * 100).toFixed(2) : null, fmt: (v) => v != null ? v.toFixed(1) + '%' : '—' }, { key: 'fromLo', label: '% above 52W Low', unit: '%', derive: (s) => s.lo52 ? +((s.price / s.lo52 - 1) * 100).toFixed(2) : null, fmt: (v) => v != null ? v.toFixed(1) + '%' : '—' }, ]; const QB_OPS = [ { key: 'gt', label: '>', test: (a, b) => a > b }, { key: 'lt', label: '<', test: (a, b) => a < b }, { key: 'gte', label: '≥', test: (a, b) => a >= b }, { key: 'lte', label: '≤', test: (a, b) => a <= b }, ]; const QB_PRESETS = [ { name: 'Momentum movers', conds: [{ field: 'chg', op: 'gt', val: 1 }, { field: 'fromHi', op: 'lt', val: 8 }] }, { name: 'Near 52W low', conds: [{ field: 'fromLo', op: 'lt', val: 15 }] }, { name: 'High volume', conds: [{ field: 'vol', op: 'gt', val: 1000000 }] }, { name: 'Pullback', conds: [{ field: 'fromHi', op: 'gt', val: 10 }, { field: 'chg', op: 'lt', val: 0 }] }, ]; function fieldVal(field, s) { const def = QB_FIELDS.find((f) => f.key === field); return def.derive ? def.derive(s) : s[field]; } function QueryBuilder({ stocks, conds, setConds, onOpenStock }) { function addCond() { setConds([...conds, { field: 'chg', op: 'gt', val: 0.5 }]); } function update(i, patch) { setConds(conds.map((c, j) => (j === i ? { ...c, ...patch } : c))); } function remove(i) { setConds(conds.filter((_, j) => j !== i)); } let results = stocks.filter((s) => conds.every((c) => { const op = QB_OPS.find((o) => o.key === c.op); const val = fieldVal(c.field, s); if (val == null) return false; return op.test(val, Number(c.val)); })); results = [...results].sort((a, b) => b.chg - a.chg); return (
| onSort(c.key) : undefined}> {c.label}{c.sortable && onSort && sortKey === c.key && {ind}} | ))}|||||||
|---|---|---|---|---|---|---|---|
| {rankBase + i + 1} |
{s.name} {s.ticker} |
₹{fmt.price(s.price)} | {s.vol != null ? fmt.vol(s.vol) : '—'} | {s.hi52 != null ? fmt.price(s.hi52) : '—'} | {s.lo52 != null ? fmt.price(s.lo52) : '—'} |