initial commit

This commit is contained in:
2026-08-05 21:35:45 +05:30
commit dbac720ce0
30 changed files with 19832 additions and 0 deletions

83
src/App.js Normal file
View File

@@ -0,0 +1,83 @@
import React, { useState } from "react";
import Chart from "./components/Chart";
import Scanner from "./components/Scanner";
import Ribbon from "./components/Ribbon";
import SmartMoney from "./components/SmartMoney";
import Popup from "./components/Popup";
import AboutScanner from "./components/AboutScanner";
import MarketIntel from "./components/MarketIntel";
import TrendScanner from "./components/TrendScanner";
import "./index.css";
function App() {
const [selectedStock, setSelectedStock] = useState("NSE:RELIANCE");
const [signal, setSignal] = useState(null);
const [view, setView] = useState("scanner");
return (
<div className="app-container">
<h1>📈 Stock Scanner Pro</h1>
<div className="nav-container">
<button
className={`nav-btn ${view === "scanner" ? "active" : ""}`}
onClick={() => setView("scanner")}
>
📊 Scanner
</button>
<button
className={`nav-btn ${view === "ribbon" ? "active" : ""}`}
onClick={() => setView("ribbon")}
>
📈 Ribbon Strategy
</button>
<button
className={`nav-btn ${view === "smartmoney" ? "active" : ""}`}
onClick={() => setView("smartmoney")}
>
🏦 Smart Money
</button>
<button
className={`nav-btn ${view === "trend" ? "active" : ""}`}
onClick={() => setView("trend")}
>
Trend Analysis
</button>
<button
className={`nav-btn ${view === "marketintel" ? "active" : ""}`}
onClick={() => setView("marketintel")}
>
📰 Market Intel
</button>
</div>
<div className="animate-fade-in">
{view === "scanner" && (
<>
<AboutScanner />
<Scanner onSelectStock={setSelectedStock} onSignal={setSignal} />
<div className="glass-card" style={{ marginTop: "20px" }}>
<h2>TradingView Chart</h2>
<Chart symbol={selectedStock} />
</div>
{signal && <Popup signal={signal} />}
</>
)}
{view === "ribbon" && <Ribbon />}
{view === "smartmoney" && <SmartMoney />}
{view === "marketintel" && <MarketIntel />}
{view === "trend" && <TrendScanner />}
</div>
</div>
);
}
export default App;

View File

@@ -0,0 +1,71 @@
import React from "react";
function AboutScanner() {
return (
<div
style={{
background: "#111827",
padding: "20px",
borderRadius: "10px",
marginBottom: "20px",
color: "white"
}}
>
<h2>🧠 How The Scanner Works</h2>
<ul>
<li>
<b>📈 Trend:</b> Price above EMA20 indicates bullish trend.
</li>
<li>
<b> Momentum:</b> RSI measures strength of buying momentum.
</li>
<li>
<b>🚀 Breakout:</b> Detects stocks breaking recent resistance levels.
</li>
<li>
<b>🔥 Volume Ratio:</b> Compares current volume with average volume.
</li>
<li>
<b>💪 Relative Strength (RS):</b> Measures stock performance vs NIFTY.
</li>
<li>
<b>🏦 Smart Money Score:</b> Estimates institutional accumulation probability.
</li>
<li>
<b>🤖 AI Score:</b> Combined score using trend, RSI, breakout, volume and RS.
</li>
<li>
<b> Confidence:</b> Probability of a quality setup based on AI Score.
</li>
<li>
<b>🎯 Fund Candidate:</b> High-volume breakout stocks showing potential accumulation.
</li>
<li>
<b>🏆 Trade Of The Day:</b> Highest ranked stock across all sectors.
</li>
</ul>
<h3>🏅 Score Guide</h3>
<ul>
<li>A+ (90-100) = Exceptional</li>
<li>A (80-89) = Strong</li>
<li>B (70-79) = Good</li>
<li>C (60-69) = Average</li>
<li>D (&lt;60) = Avoid</li>
</ul>
</div>
);
}
export default AboutScanner;

163
src/components/Backtest.js Normal file
View File

@@ -0,0 +1,163 @@
import React, { useEffect, useState } from "react";
import axios from "axios";
function Backtest() {
const [data, setData] = useState({});
// ✅ Fetch backtest data
const loadBacktest = async () => {
try {
const res = await axios.get("http://127.0.0.1:8000/backtest");
setData(res.data);
} catch (err) {
console.error("Backtest Error:", err);
}
};
useEffect(() => {
loadBacktest();
}, []);
return (
<div
style={{
background: "#0d1117",
color: "#c9d1d9",
padding: 20,
minHeight: "100vh",
}}
>
<h1 style={{ color: "#58a6ff" }}>
📊 Backtest Dashboard (Strategy Performance)
</h1>
{/* ✅ EXPLANATION PANEL */}
<div
style={{
background: "#161b22",
border: "1px solid #30363d",
padding: 15,
borderRadius: 8,
marginBottom: 20,
}}
>
<h2 style={{ color: "#58a6ff" }}>📘 How to Read Backtest</h2>
<p>
<b>Trades</b> = Total opportunities generated
</p>
<p>
<b>Wins</b> = Profitable trades
</p>
<p>
<b>Loss</b> = Losing trades
</p>
<p>
<b>Win Rate</b> = Success % of strategy
</p>
<p>
<b>Profit</b> = Net gain (simulated)
</p>
<br />
<p>
💡 <b>Best Strategy Rules:</b>
</p>
<ul>
<li>Win Rate 60% </li>
<li>Trades 10 </li>
<li>Profit positive </li>
</ul>
</div>
{/* ✅ SECTORS */}
{Object.entries(data).map(([sector, stocks]) => (
<div
key={sector}
style={{
background: "#161b22",
border: "1px solid #30363d",
padding: 15,
marginBottom: 20,
borderRadius: 10,
}}
>
<h2 style={{ color: "#58a6ff" }}>
{sector}
</h2>
<table
width="100%"
style={{
borderCollapse: "collapse",
textAlign: "center",
}}
>
<thead>
<tr style={{ borderBottom: "1px solid #30363d" }}>
<th>Stock</th>
<th>Trades</th>
<th>Wins</th>
<th>Loss</th>
<th>Win %</th>
<th>Profit</th>
</tr>
</thead>
<tbody>
{stocks.map((s, i) => (
<tr
key={i}
style={{
borderBottom: "1px solid #30363d",
}}
>
<td>{s.symbol}</td>
<td>{s.trades}</td>
<td style={{ color: "#3fb950" }}>
{s.wins}
</td>
<td style={{ color: "#f85149" }}>
{s.loss}
</td>
{/* ✅ WIN RATE COLOR */}
<td
style={{
color:
s.win_rate >= 70
? "#3fb950"
: s.win_rate >= 60
? "#d29922"
: "#f85149",
fontWeight: "bold",
}}
>
{s.win_rate}%
</td>
{/* ✅ PROFIT COLOR */}
<td
style={{
color:
s.profit > 0 ? "#3fb950" : "#f85149",
fontWeight: "bold",
}}
>
{s.profit}
</td>
</tr>
))}
</tbody>
</table>
</div>
))}
</div>
);
}
export default Backtest;

149
src/components/Chart.js vendored Normal file
View File

@@ -0,0 +1,149 @@
import React, { useEffect, useRef } from "react";
import { createChart, CandlestickSeries, LineSeries } from "lightweight-charts";
import axios from "axios";
function Chart({ symbol }) {
const ref = useRef(null);
useEffect(() => {
if (!ref.current || !symbol) return;
ref.current.innerHTML = "";
try {
const chart = createChart(ref.current, {
width: 800,
height: 500,
layout: {
background: { color: "#111" },
textColor: "#DDD",
},
grid: {
vertLines: { color: "#333" },
horzLines: { color: "#333" },
},
});
// ✅ MAIN CANDLE SERIES
const candleSeries = chart.addSeries(CandlestickSeries);
// ✅ EMA LINE
const emaSeries = chart.addSeries(LineSeries, {
color: "yellow",
lineWidth: 2,
});
// ✅ RSI LINE (drawn on same chart for simplicity)
const rsiSeries = chart.addSeries(LineSeries, {
color: "cyan",
lineWidth: 1,
});
// ✅ EMA CALCULATION
const calculateEMA = (data, period = 20) => {
const k = 2 / (period + 1);
let ema = data[0].close;
return data.map((d) => {
ema = d.close * k + ema * (1 - k);
return { time: d.time, value: ema };
});
};
// ✅ RSI CALCULATION
const calculateRSI = (data, period = 14) => {
let gains = 0;
let losses = 0;
const result = [];
for (let i = 1; i < data.length; i++) {
const diff = data[i].close - data[i - 1].close;
if (diff > 0) gains += diff;
else losses -= diff;
if (i >= period) {
const rs = gains / (losses || 1);
const rsi = 100 - 100 / (1 + rs);
result.push({ time: data[i].time, value: rsi });
}
}
return result;
};
// ✅ LOAD DATA FUNCTION
const loadData = () => {
axios
.get(`http://localhost:8000/history?symbol=${symbol}`)
.then((res) => {
if (!res.data || res.data.length === 0) return;
const formatted = res.data.map((d) => ({
time: Math.floor(d.time),
open: Number(d.open),
high: Number(d.high),
low: Number(d.low),
close: Number(d.close),
}));
// ✅ SET CANDLES
candleSeries.setData(formatted);
// ✅ EMA
const emaData = calculateEMA(formatted);
emaSeries.setData(emaData);
// ✅ RSI
const rsiData = calculateRSI(formatted);
rsiSeries.setData(rsiData);
// ✅ ENTRY / SL / TARGET
const lastPrice = formatted[formatted.length - 1].close;
candleSeries.createPriceLine({
price: lastPrice,
color: "blue",
lineWidth: 2,
title: "Entry",
});
candleSeries.createPriceLine({
price: lastPrice * 0.97,
color: "red",
title: "SL",
});
candleSeries.createPriceLine({
price: lastPrice * 1.05,
color: "green",
title: "Target",
});
chart.timeScale().fitContent();
})
.catch((err) => console.error(err));
};
// ✅ INITIAL LOAD
loadData();
// ✅ LIVE UPDATE (every 1 min)
const interval = setInterval(loadData, 60000);
return () => {
clearInterval(interval);
chart.remove();
};
} catch (err) {
console.error("Chart crash:", err);
}
}, [symbol]);
return <div ref={ref}></div>;
}
export default Chart;

View File

@@ -0,0 +1,21 @@
import React from "react";
function ChartPage({ symbol }) {
const tvSymbol = symbol || "NSE:RELIANCE";
const url = `https://www.tradingview.com/chart/?symbol=${tvSymbol}`;
return (
<div style={{ width: "100%", height: "600px", marginTop: "20px" }}>
<iframe
title="TradingView Chart"
src={url}
width="100%"
height="100%"
frameBorder="0"
></iframe>
</div>
);
}
export default ChartPage;

114
src/components/LongTerm.js Normal file
View File

@@ -0,0 +1,114 @@
import React, { useEffect, useState } from "react";
import axios from "axios";
function LongTerm() {
const [data, setData] = useState({});
const loadData = async () => {
try {
const res = await axios.get("http://127.0.0.1:8000/longterm");
setData(res.data);
} catch (err) {
console.error(err);
}
};
useEffect(() => {
loadData();
}, []);
return (
<div style={{
background: "#0d1117",
color: "#c9d1d9",
padding: 20,
minHeight: "100vh"
}}>
<h1 style={{ color: "#58a6ff" }}>
📈 Long-Term Investment Dashboard
</h1>
{/* ✅ EXPLANATION */}
<div style={{
background: "#161b22",
padding: 15,
borderRadius: 10,
marginBottom: 20
}}>
<h3>📘 Strategy</h3>
<ul>
<li> Golden Cross = 50 EMA &gt; 200 EMA</li>
<li> Support = Price above 200 EMA</li>
<li> Momentum = Breakout + Volume</li>
</ul>
<p>💡 Only strong trend reversal stocks are shown</p>
</div>
{Object.entries(data).map(([sector, info]) => {
const filtered = info.stocks.filter(
s => s.golden_cross || s.support_strength
);
if (filtered.length === 0) return null;
return (
<div key={sector} style={{
background: "#161b22",
padding: 15,
marginBottom: 20,
borderRadius: 10
}}>
<h2 style={{ color: "#3fb950" }}>
{sector} Long-Term Strong
</h2>
<table width="100%" style={{ textAlign: "center" }}>
<thead>
<tr>
<th>Stock</th>
<th>Score</th>
<th>RSI</th>
<th>Golden Cross</th>
<th>Support</th>
<th>Signal</th>
</tr>
</thead>
<tbody>
{filtered.map((s, i) => (
<tr key={i}>
<td>{s.symbol}</td>
<td>{s.score}</td>
<td>{s.rsi}</td>
<td style={{ color: "#3fb950" }}>
</td>
<td style={{ color: "#3fb950" }}>
</td>
<td style={{ color: "#3fb950" }}>
{s.signal}
</td>
</tr>
))}
</tbody>
</table>
</div>
);
})}
</div>
);
}
export default LongTerm;

View File

@@ -0,0 +1,112 @@
import React, { useEffect, useState } from "react";
import axios from "axios";
function MarketIntel() {
const [data, setData] = useState(null);
useEffect(() => {
loadData();
}, []);
const loadData = async () => {
try {
const res = await axios.get("http://127.0.0.1:8000/marketintel");
setData(res.data);
} catch (err) {
console.error(err);
}
};
if (!data) {
return <div className="glass-card" style={{ textAlign: "center" }}>Loading Market Intelligence...</div>;
}
return (
<div className="animate-fade-in">
<h2 className="text-blue" style={{ fontSize: "2rem", marginBottom: "20px" }}>📰 Market Intelligence (Live)</h2>
<div style={{ display: "grid", gridTemplateColumns: "1fr", gap: "20px", marginBottom: "30px" }}>
{/* Top News */}
<div className="glass-card">
<h2 className="text-orange">🔥 Latest Financial News</h2>
<div style={{ display: "flex", flexDirection: "column", gap: "12px" }}>
{(data.top_news || []).length > 0 ? (
(data.top_news || []).map((n, i) => (
<div key={i} style={{ padding: "12px", background: "rgba(255,255,255,0.03)", borderRadius: "8px", borderLeft: "3px solid var(--accent-blue)" }}>
<a href={n.link} target="_blank" rel="noreferrer" style={{ color: "var(--text-primary)", textDecoration: "none", fontWeight: 600, fontSize: "1.05rem" }}>
{n.title}
</a>
<div style={{ fontSize: "0.85rem", color: "var(--text-secondary)", marginTop: "6px" }}>
{n.provider} {new Date(n.pubDate).toLocaleString()}
</div>
</div>
))
) : (
<p className="text-muted">No news available at the moment.</p>
)}
</div>
</div>
</div>
<div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(300px, 1fr))", gap: "20px" }}>
{/* Block Deals */}
<div className="glass-card">
<h2 className="text-green">💰 Block Deals</h2>
<div className="data-table-container">
<table className="data-table">
<thead><tr><th>Stock</th><th>Buyer</th><th>Value</th></tr></thead>
<tbody>
{(data.block_deals || []).map((d, i) => (
<tr key={i}><td>{d.stock}</td><td>{d.buyer}</td><td>{d.value}</td></tr>
))}
</tbody>
</table>
</div>
</div>
{/* Bulk Deals */}
<div className="glass-card">
<h2 className="text-green">📦 Bulk Deals</h2>
<div className="data-table-container">
<table className="data-table">
<thead><tr><th>Stock</th><th>Buyer</th><th>Shares</th></tr></thead>
<tbody>
{(data.bulk_deals || []).map((d, i) => (
<tr key={i}><td>{d.stock}</td><td>{d.buyer}</td><td>{d.shares}</td></tr>
))}
</tbody>
</table>
</div>
</div>
{/* FII / DII */}
<div className="glass-card">
<h2 className="text-blue">🏦 Institutional Activity</h2>
<div className="data-table-container">
<table className="data-table">
<thead><tr><th>Institution</th><th>Stock</th><th>Activity</th></tr></thead>
<tbody>
{(data.fii_activity || []).map((d, i) => (
<tr key={`fii-${i}`}>
<td><span className="badge badge-neutral">FII</span></td>
<td>{d.stock}</td>
<td><span className={`badge ${d.activity.includes('Buy') ? 'badge-success' : 'badge-danger'}`}>{d.activity}</span></td>
</tr>
))}
{(data.dii_activity || []).map((d, i) => (
<tr key={`dii-${i}`}>
<td><span className="badge badge-neutral">DII</span></td>
<td>{d.stock}</td>
<td><span className={`badge ${d.activity.includes('Buy') ? 'badge-success' : 'badge-danger'}`}>{d.activity}</span></td>
</tr>
))}
</tbody>
</table>
</div>
</div>
</div>
</div>
);
}
export default MarketIntel;

22
src/components/Popup.js Normal file
View File

@@ -0,0 +1,22 @@
import React, { useEffect } from "react";
function Popup({ signal }) {
useEffect(() => {
const timer = setTimeout(() => {
const popup = document.getElementById("popup");
if (popup) popup.style.display = "none";
}, 4000);
return () => clearTimeout(timer);
}, []);
return (
<div id="popup" className="popup">
<h3>🚨 Trade Signal</h3>
<p>Stock: {signal.name}</p>
<p>Code: {signal.code}</p>
</div>
);
}
export default Popup;

81
src/components/Ribbon.js Normal file
View File

@@ -0,0 +1,81 @@
import React, { useEffect, useState } from "react";
import axios from "axios";
function Ribbon() {
const [data, setData] = useState([]);
const [loading, setLoading] = useState(true);
const loadData = async () => {
try {
const res = await axios.get("http://127.0.0.1:8000/ribbon");
setData(res.data || []);
setLoading(false);
} catch (err) {
console.error("Ribbon error:", err);
setLoading(false);
}
};
useEffect(() => {
loadData();
const interval = setInterval(loadData, 100000);
return () => clearInterval(interval);
}, []);
const openChart = (symbol) => {
window.open(`https://www.tradingview.com/chart/?symbol=NSE:${symbol}`, "_blank");
};
if (loading) return <div className="glass-card" style={{ textAlign: "center" }}>Loading Ribbon...</div>;
return (
<div className="glass-card animate-fade-in">
<h2 className="text-blue">📈 EMA Ribbon Strategy</h2>
<div className="data-table-container">
<table className="data-table">
<thead>
<tr>
<th>Stock</th>
<th>Price</th>
<th>EMA High 5</th>
<th>EMA Low 5</th>
<th>EMA High 100</th>
<th>EMA Low 100</th>
<th>EMA Close 100</th>
<th>Signal</th>
<th>Action</th>
</tr>
</thead>
<tbody>
{(data || []).map((s, i) => (
<tr key={i}>
<td style={{ fontWeight: 600 }}>{s.symbol}</td>
<td>{s.price}</td>
<td>{s.ema_high_5}</td>
<td>{s.ema_low_5}</td>
<td>{s.ema_high_100}</td>
<td>{s.ema_low_100}</td>
<td className="text-blue">{s.ema_close_100}</td>
<td>
<span className={`badge ${
s.signal.includes("BUY") ? "badge-success" :
s.signal.includes("SELL") ? "badge-danger" : "badge-warning"
}`}>
{s.signal}
</span>
</td>
<td>
<button className="action-btn" onClick={() => openChart(s.symbol)}>
Chart
</button>
</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
);
}
export default Ribbon;

144
src/components/Scanner.js Normal file
View File

@@ -0,0 +1,144 @@
import React, { useEffect, useState } from "react";
import axios from "axios";
function Scanner({ onSelectStock, onSignal }) {
const [data, setData] = useState(null);
const [lastBest, setLastBest] = useState(null);
const loadData = async () => {
try {
const res = await axios.get("http://127.0.0.1:8000/scan");
const newData = res.data;
const best = newData.best_5 && newData.best_5.length > 0 ? newData.best_5[0] : null;
if (best && best.symbol !== lastBest) {
if (onSignal) onSignal(`New Best Trade: ${best.symbol}`);
setLastBest(best.symbol);
}
setData(newData);
} catch (err) {
console.error(err);
}
};
useEffect(() => {
loadData();
const interval = setInterval(loadData, 100000);
return () => clearInterval(interval);
}, []);
const openChart = (symbol) => {
window.open(`https://www.tradingview.com/chart/?symbol=NSE:${symbol}`, "_blank");
};
if (!data) return <div className="glass-card" style={{ textAlign: "center" }}>Loading Scanner Data...</div>;
return (
<div>
{/* Top 5 Trades */}
{(data.best_5 || []).length > 0 && (
<div className="glass-card animate-fade-in" style={{ marginBottom: "30px", borderLeft: "4px solid var(--accent-green)" }}>
<h2 className="text-green">🔥 Top 5 Momentum Picks</h2>
<div className="data-table-container">
<table className="data-table">
<thead>
<tr>
<th>Stock</th>
<th>Price</th>
<th>RSI</th>
<th>MACD</th>
<th>Signal</th>
<th>AI Score</th>
<th>Grade</th>
<th>Institutional</th>
<th>Action</th>
</tr>
</thead>
<tbody>
{(data.best_5 || []).filter(s => s).map((s, i) => (
<tr key={i}>
<td style={{ fontWeight: 600 }}>{s?.symbol}</td>
<td>{s?.price}</td>
<td><span className={`badge ${s?.rsi > 60 ? 'badge-success' : 'badge-neutral'}`}>{s?.rsi}</span></td>
<td><span className={`badge ${s?.macd_hist > 0 ? 'badge-success' : 'badge-danger'}`}>{s?.macd_hist}</span></td>
<td>
<span className={`badge ${s?.signal?.includes("BUY") ? 'badge-success' : 'badge-danger'}`}>
{s?.signal}
</span>
</td>
<td>{s.ai_score} / 100</td>
<td>{s.grade}</td>
<td>{s.institutional ? <span className="text-orange">🔥 Yes</span> : <span className="text-muted">No</span>}</td>
<td>
<button className="action-btn" onClick={() => { openChart(s?.symbol); onSelectStock(s?.symbol); }}>
View Chart
</button>
</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
)}
{/* Sector Tables */}
{Object.entries(data.sectors || {}).map(([sector, info]) => {
const best = info.top_stock;
return (
<div key={sector} className="glass-card animate-fade-in" style={{ marginBottom: "20px" }}>
<h2 className="text-blue">{sector} ({info.stocks.length} Stocks)</h2>
{best && (
<p className="text-orange" style={{ marginBottom: "20px" }}>
<strong>Top Pick:</strong> {best.symbol} (Score: {best.score})
</p>
)}
<div className="data-table-container">
<table className="data-table">
<thead>
<tr>
<th>Stock</th>
<th>Price</th>
<th>MACD</th>
<th>Signal</th>
<th>Volume</th>
<th>Target</th>
<th>AI Score</th>
<th>Action</th>
</tr>
</thead>
<tbody>
{(info.stocks || []).map((s, i) => (
<tr key={i}>
<td style={{ fontWeight: 500 }}>{s?.symbol}</td>
<td>{s?.price}</td>
<td><span className={`badge ${s?.macd_hist > 0 ? 'badge-success' : 'badge-danger'}`}>{s?.macd_hist}</span></td>
<td>
<span className={`badge ${s?.signal?.includes("BUY") ? 'badge-success' : 'badge-danger'}`}>
{s?.signal}
</span>
</td>
<td>{s?.volume?.toLocaleString()}</td>
<td className="text-green">{s?.target}</td>
<td>{s?.ai_score}</td>
<td>
<button className="action-btn" onClick={() => { openChart(s?.symbol); onSelectStock(s?.symbol); }}>
Chart
</button>
</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
);
})}
</div>
);
}
export default Scanner;

View File

@@ -0,0 +1,95 @@
import React, { useEffect, useState } from "react";
import axios from "axios";
function SmartMoney() {
const [data, setData] = useState(null);
useEffect(() => {
loadData();
const interval = setInterval(loadData, 100000);
return () => clearInterval(interval);
}, []);
const loadData = async () => {
try {
const res = await axios.get("http://127.0.0.1:8000/smartmoney");
setData(res.data);
} catch (err) {
console.error(err);
}
};
const openChart = (symbol) => {
window.open(`https://www.tradingview.com/chart/?symbol=NSE:${symbol}`, "_blank");
};
if (!data) return <div className="glass-card" style={{ textAlign: "center" }}>Loading Smart Money Data...</div>;
return (
<div className="animate-fade-in">
<h2 className="text-blue" style={{ fontSize: "2rem", marginBottom: "20px" }}>🏦 Smart Money Tracker</h2>
{/* Trade of the Day */}
{data.trade_of_day && (
<div className="glass-card" style={{ marginBottom: "20px", borderLeft: "4px solid var(--accent-orange)" }}>
<h2 className="text-orange">🔥 Institutional Trade of the Day: {data.trade_of_day.symbol}</h2>
<p className="text-muted" style={{ marginBottom: "12px" }}>
Massive volume spike combined with strong momentum indicating potential smart money buying.
</p>
<div style={{ display: "flex", gap: "15px", flexWrap: "wrap", marginBottom: "15px" }}>
<span className="badge badge-neutral">Volume Ratio: {data.trade_of_day.volume_ratio}x</span>
<span className="badge badge-neutral">RSI: {data.trade_of_day.rsi}</span>
<span className="badge badge-success">{data.trade_of_day.reason}</span>
</div>
<button className="nav-btn active" onClick={() => openChart(data.trade_of_day.symbol)}>
View Deep Chart
</button>
</div>
)}
{/* Top 10 Institutional Buys */}
<div className="glass-card">
<h2 className="text-green">Top 10 Institutional Breakouts</h2>
<div className="data-table-container">
<table className="data-table">
<thead>
<tr>
<th>Stock</th>
<th>Inst Label</th>
<th>Inst Score</th>
<th>Volume Ratio</th>
<th>Breakout</th>
<th>Reason</th>
<th>Action</th>
</tr>
</thead>
<tbody>
{(data.top_10 || []).map((s, i) => (
<tr key={i}>
<td style={{ fontWeight: 600 }}>{s.symbol}</td>
<td>
<span className={`badge ${
s.institutional_label.includes("Very Strong") ? 'badge-success' :
s.institutional_label.includes("Strong") ? 'badge-success' : 'badge-neutral'
}`}>
{s.institutional_label}
</span>
</td>
<td>{s.institutional_score}</td>
<td><span className="text-orange">{s.volume_ratio}x</span></td>
<td>{s.breakout ? "🔥 YES" : "NO"}</td>
<td>{s.reason}</td>
<td>
<button className="action-btn" onClick={() => openChart(s.symbol)}>Chart</button>
</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
</div>
);
}
export default SmartMoney;

View File

@@ -0,0 +1,78 @@
import React, { useEffect, useState } from "react";
import axios from "axios";
function TrendScanner() {
const [data, setData] = useState(null);
useEffect(() => {
loadData();
const interval = setInterval(loadData, 100000);
return () => clearInterval(interval);
}, []);
const loadData = async () => {
try {
const res = await axios.get("http://127.0.0.1:8000/trend");
setData(res.data);
} catch (err) {
console.error(err);
}
};
const openChart = (symbol) => {
window.open(`https://www.tradingview.com/chart/?symbol=NSE:${symbol}`, "_blank");
};
if (!data) return <div className="glass-card" style={{ textAlign: "center" }}>Loading Trend Data...</div>;
return (
<div className="animate-fade-in">
<h2 className="text-blue" style={{ fontSize: "2rem", marginBottom: "20px" }}> Top Trending Stocks</h2>
<div className="glass-card">
<h2 className="text-green">Top 20 Trend Analysis</h2>
<div className="data-table-container">
<table className="data-table">
<thead>
<tr>
<th>Stock</th>
<th>Trend Signal</th>
<th>Trend Score</th>
<th>Relative Strength</th>
<th>Trend Reason</th>
<th>Action</th>
</tr>
</thead>
<tbody>
{(data.top_20 || []).map((s, i) => (
<tr key={i}>
<td style={{ fontWeight: 600 }}>{s.symbol}</td>
<td>
<span className={`badge ${
s.trend_signal.includes("BUY") ? 'badge-success' :
s.trend_signal.includes("WATCH") ? 'badge-warning' : 'badge-danger'
}`}>
{s.trend_signal}
</span>
</td>
<td>{s.trend_score}</td>
<td>
<span className={s.relative_strength > 0 ? "text-green" : "text-red"}>
{s.relative_strength}%
</span>
</td>
<td>{s.trend_reason}</td>
<td>
<button className="action-btn" onClick={() => openChart(s.symbol)}>Chart</button>
</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
</div>
);
}
export default TrendScanner;

216
src/index.css Normal file
View File

@@ -0,0 +1,216 @@
:root {
/* Color Palette - Premium Dark Theme */
--bg-primary: #0b1220;
--bg-secondary: #111827;
--bg-tertiary: #1f2937;
--text-primary: #f8fafc;
--text-secondary: #94a3b8;
--text-muted: #64748b;
--accent-blue: #3b82f6;
--accent-blue-hover: #2563eb;
--accent-green: #10b981;
--accent-green-bg: rgba(16, 185, 129, 0.1);
--accent-red: #ef4444;
--accent-red-bg: rgba(239, 68, 68, 0.1);
--accent-orange: #f59e0b;
--accent-orange-bg: rgba(245, 158, 11, 0.1);
/* Borders & Shadows */
--border-color: rgba(255, 255, 255, 0.05);
--glass-bg: rgba(17, 24, 39, 0.7);
--shadow-sm: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
--shadow-glow: 0 0 15px rgba(59, 130, 246, 0.3);
}
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap');
body {
margin: 0;
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
background-color: var(--bg-primary);
color: var(--text-primary);
}
* {
box-sizing: border-box;
}
/* Glassmorphism Card */
.glass-card {
background: var(--glass-bg);
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
border: 1px solid var(--border-color);
border-radius: 16px;
padding: 24px;
box-shadow: var(--shadow-sm);
transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.glass-card:hover {
transform: translateY(-2px);
box-shadow: var(--shadow-glow);
}
/* Typography */
h1 {
font-size: 2.5rem;
font-weight: 800;
background: linear-gradient(135deg, #fff, #94a3b8);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
margin-bottom: 2rem;
}
h2 {
font-size: 1.5rem;
font-weight: 600;
color: var(--text-primary);
margin-bottom: 1.5rem;
}
/* Buttons */
.nav-btn {
background: var(--bg-tertiary);
color: var(--text-primary);
border: 1px solid var(--border-color);
padding: 10px 20px;
border-radius: 8px;
font-size: 0.95rem;
font-weight: 500;
cursor: pointer;
transition: all 0.2s ease;
margin-right: 12px;
margin-bottom: 12px;
display: inline-flex;
align-items: center;
gap: 8px;
}
.nav-btn:hover {
background: var(--bg-secondary);
border-color: var(--accent-blue);
box-shadow: 0 0 10px rgba(59, 130, 246, 0.2);
transform: translateY(-1px);
}
.nav-btn.active {
background: var(--accent-blue);
border-color: var(--accent-blue-hover);
color: white;
}
.action-btn {
background: rgba(255, 255, 255, 0.05);
color: var(--text-primary);
border: 1px solid var(--border-color);
padding: 6px 12px;
border-radius: 6px;
font-size: 0.85rem;
cursor: pointer;
transition: all 0.2s ease;
}
.action-btn:hover {
background: rgba(255, 255, 255, 0.1);
border-color: rgba(255, 255, 255, 0.2);
}
/* Modern Tables */
.data-table-container {
overflow-x: auto;
border-radius: 12px;
border: 1px solid var(--border-color);
background: var(--bg-secondary);
}
.data-table {
width: 100%;
border-collapse: separate;
border-spacing: 0;
text-align: left;
}
.data-table th {
background: rgba(0, 0, 0, 0.2);
color: var(--text-secondary);
font-weight: 600;
font-size: 0.85rem;
text-transform: uppercase;
letter-spacing: 0.05em;
padding: 16px;
border-bottom: 1px solid var(--border-color);
white-space: nowrap;
}
.data-table td {
padding: 16px;
border-bottom: 1px solid rgba(255, 255, 255, 0.02);
color: var(--text-primary);
font-size: 0.95rem;
vertical-align: middle;
}
.data-table tr:last-child td {
border-bottom: none;
}
.data-table tr:hover td {
background: rgba(255, 255, 255, 0.02);
}
/* Status Badges */
.badge {
padding: 4px 10px;
border-radius: 20px;
font-size: 0.8rem;
font-weight: 600;
display: inline-block;
}
.badge-success { background: var(--accent-green-bg); color: var(--accent-green); border: 1px solid rgba(16, 185, 129, 0.2); }
.badge-danger { background: var(--accent-red-bg); color: var(--accent-red); border: 1px solid rgba(239, 68, 68, 0.2); }
.badge-warning { background: var(--accent-orange-bg); color: var(--accent-orange); border: 1px solid rgba(245, 158, 11, 0.2); }
.badge-neutral { background: var(--bg-tertiary); color: var(--text-secondary); border: 1px solid var(--border-color); }
/* Layouts */
.app-container {
max-width: 1400px;
margin: 0 auto;
padding: 40px 20px;
}
.nav-container {
display: flex;
flex-wrap: wrap;
gap: 12px;
margin-bottom: 40px;
padding-bottom: 20px;
border-bottom: 1px solid var(--border-color);
}
/* Animations */
@keyframes fadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
.animate-fade-in {
animation: fadeIn 0.4s ease-out forwards;
}
/* Utilities */
.text-green { color: var(--accent-green); }
.text-red { color: var(--accent-red); }
.text-orange { color: var(--accent-orange); }
.text-blue { color: var(--accent-blue); }
.text-muted { color: var(--text-muted); }

10
src/index.js Normal file
View File

@@ -0,0 +1,10 @@
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);

33
src/styles.css Normal file
View File

@@ -0,0 +1,33 @@
.table {
width: 100%;
border-collapse: collapse;
margin-top: 20px;
background: #1c1c1c;
}
.table th, .table td {
border: 1px solid #333;
padding: 10px;
text-align: center;
}
.table th {
background: #222;
}
.table tr:hover {
background: #2a2a2a;
cursor: pointer;
}
td:nth-child(3) {
color: #00e676;
}
td:nth-child(5) {
color: red;
}
td:nth-child(6) {
color: #00c853;
}