Customize - Stock map list, watch list, home page

This commit is contained in:
2026-08-05 23:51:18 +05:30
parent 076c4ff68f
commit 53ad1abb78
34 changed files with 1423 additions and 587 deletions

View File

@@ -0,0 +1,14 @@
FROM python:3.13-slim
WORKDIR /app
RUN apt-get update && apt-get install -y git cmake g++ && rm -rf /var/lib/apt/lists/*
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 8000
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]

View File

@@ -26,6 +26,9 @@ class ProfileUpdateRequest(BaseModel):
gender: str = None
password: str = None # Base64 encoded RSA-encrypted new password
class SectorMapUpdateRequest(BaseModel):
sector_map: dict
@router.get("/public-key")
def get_public_key():
return {"public_key": public_key.decode("utf-8")}
@@ -84,9 +87,16 @@ def get_me(current_user: User = Depends(get_current_user)):
"display_name": current_user.display_name,
"email_id": current_user.email_id,
"mobile_no": current_user.mobile_no,
"gender": current_user.gender
"gender": current_user.gender,
"sector_map": current_user.sector_map
}
@router.put("/update-sectors")
def update_sectors(req: SectorMapUpdateRequest, current_user: User = Depends(get_current_user), db: Session = Depends(get_db)):
current_user.sector_map = req.sector_map
db.commit()
return {"message": "Sectors updated successfully"}
@router.put("/update-profile")
def update_profile(req: ProfileUpdateRequest, current_user: User = Depends(get_current_user), db: Session = Depends(get_db)):
if req.display_name is not None:

View File

@@ -4,24 +4,56 @@ from app.services.stock_engine import (
get_scan, get_ribbon, get_smartmoney, get_trend, get_marketintel
)
import requests
router = APIRouter()
@router.get("/scan")
def scan(current_user = Depends(get_current_user)):
return get_scan()
return get_scan(current_user.sector_map or {})
@router.get("/ribbon")
def ribbon(current_user = Depends(get_current_user)):
return get_ribbon()
return get_ribbon(current_user.sector_map or {})
@router.get("/smartmoney")
def smartmoney(current_user = Depends(get_current_user)):
return get_smartmoney()
return get_smartmoney(current_user.sector_map or {})
@router.get("/trend")
def trend(current_user = Depends(get_current_user)):
return get_trend()
return get_trend(current_user.sector_map or {})
@router.get("/marketintel")
def marketintel(current_user = Depends(get_current_user)):
return get_marketintel()
@router.get("/search")
def search(q: str, current_user = Depends(get_current_user)):
headers = {'User-Agent': 'Mozilla/5.0'}
url = f"https://query2.finance.yahoo.com/v1/finance/search?q={q}&quotesCount=10&newsCount=0"
res = requests.get(url, headers=headers)
if res.status_code == 200:
data = res.json()
quotes = data.get("quotes", [])
# Filter for Indian stocks (.NS or .BO)
indian_stocks = [q for q in quotes if q.get("symbol", "").endswith((".NS", ".BO"))][:10]
if indian_stocks:
import yfinance as yf
symbols = [q["symbol"] for q in indian_stocks]
tickers = yf.Tickers(" ".join(symbols))
for stock in indian_stocks:
try:
info = tickers.tickers[stock["symbol"]].info
stock["currentPrice"] = info.get("currentPrice") or info.get("regularMarketPrice")
stock["marketCap"] = info.get("marketCap")
except Exception as e:
print(f"Error fetching {stock['symbol']}: {e}")
stock["currentPrice"] = None
stock["marketCap"] = None
return indian_stocks
return []

View File

@@ -1,6 +1,6 @@
import os
DATABASE_URL = "postgresql://postgres:M%40triXPostgr3s%406202@103.125.129.116:5333/stock_scanner"
DATABASE_URL = os.getenv("DATABASE_URL", "postgresql://postgres:M%40triXPostgr3s%406202@host.docker.internal:5333/stock_scanner")
SECRET_KEY = "stock-scanner-super-secret-key-12345"
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 60

View File

@@ -1,4 +1,4 @@
from sqlalchemy import Column, Integer, String
from sqlalchemy import Column, Integer, String, JSON
from app.db.database import Base
class User(Base):
@@ -11,3 +11,4 @@ class User(Base):
email_id = Column(String, nullable=True)
mobile_no = Column(String, nullable=True)
gender = Column(String, nullable=True)
sector_map = Column(JSON, nullable=True)

View File

@@ -425,12 +425,12 @@ def analyze(stock):
# =========================================
# ✅ API - FAST SCAN
# =========================================
def get_scan():
def get_scan(user_sector_map):
sector_output = {}
all_stocks = []
for sector, stocks in sector_map.items():
for sector, stocks in user_sector_map.items():
data = list(ThreadPoolExecutor(5).map(analyze, stocks))
data = [x for x in data if x]
@@ -536,26 +536,28 @@ def analyze_ribbon(stock):
return None
def get_ribbon():
def get_ribbon(user_sector_map):
results = []
for stocks in sector_map.values():
for sector, stocks in user_sector_map.items():
data = list(ThreadPoolExecutor(5).map(analyze_ribbon, stocks))
data = [x for x in data if x]
for x in data:
x["sector"] = sector
results.extend(data)
return results
def get_smartmoney():
def get_smartmoney(user_sector_map):
results = []
for sector, stocks in sector_map.items():
for sector, stocks in user_sector_map.items():
data = list(ThreadPoolExecutor(5).map(analyze, stocks))
data = [x for x in data if x]
for x in data:
x["sector"] = sector
results.extend(data)
@@ -575,15 +577,15 @@ def get_smartmoney():
"all": results
}
def get_trend():
def get_trend(user_sector_map):
results = []
for sector, stocks in sector_map.items():
for sector, stocks in user_sector_map.items():
data = list(ThreadPoolExecutor(5).map(analyze, stocks))
data = [x for x in data if x]
for x in data:
x["sector"] = sector
results.extend(data)
results.sort(

114
backend/requirements.txt Normal file
View File

@@ -0,0 +1,114 @@
alembic==1.18.5
annotated-doc==0.0.4
annotated-types==0.7.0
anyio==4.12.1
APScheduler==3.11.2
argon2-cffi==25.1.0
argon2-cffi-bindings==25.1.0
bcrypt==5.0.0
beautifulsoup4==4.15.0
cachetools==7.0.5
certifi==2026.1.4
cffi==2.0.0
charset-normalizer==3.4.7
click==8.3.1
cryptography==48.0.0
curl_cffi==0.16.0
defusedxml==0.7.1
dnspython==2.8.0
-e git+https://github.com/maddy23285/docvision.git@b0a6bea7ad1db9f515c9128964370c6bfdaad9e1#egg=docfingerprint
-e git+https://github.com/maddy23285/docvision.git@b0a6bea7ad1db9f515c9128964370c6bfdaad9e1#egg=docfingerprint_embedding&subdirectory=embedding_service
ecdsa==0.19.2
email-validator==2.3.0
fastapi==0.128.0
filelock==3.17.0
fonttools==4.62.1
fpdf2==2.8.7
fsspec==2025.2.0
h11==0.16.0
hf-xet==1.5.2
httpcore==1.0.9
httptools==0.7.1
httpx==0.28.1
huggingface_hub==0.36.2
idna==3.11
ImageHash==4.3.2
imap-tools==1.13.0
iniconfig==2.3.0
Jinja2==3.1.4
lxml==6.1.1
Mako==1.3.12
MarkupSafe==3.0.2
mpmath==1.3.0
multitasking==0.0.13
networkx==3.4.2
numpy==2.2.3
ollama==0.6.2
opencv-python==4.12.0.88
opencv-python-headless==4.13.0.92
packaging==26.2
pandas==3.0.5
passlib==1.7.4
pdf2image==1.17.0
pdfminer.six==20251230
pdfplumber==0.11.9
peewee==4.3.0
pgvector==0.5.0
pillow==11.1.0
platformdirs==4.11.0
pluggy==1.6.0
protobuf==7.35.1
psycopg==3.3.4
psycopg-binary==3.3.4
psycopg2-binary==2.9.11
pyasn1==0.6.4
pycparser==3.0
pycryptodome==3.23.0
pycryptodomex==3.21.0
pydantic==2.12.5
pydantic-settings==2.14.2
pydantic_core==2.41.5
Pygments==2.20.0
PyJWT==2.11.0
pypdf==6.13.0
pypdfium2==5.9.0
pytesseract==0.3.13
pytest==8.4.2
pytest-asyncio==0.26.0
python-dateutil==2.9.0.post0
python-docx==1.2.0
python-dotenv==1.2.1
python-jose==3.5.0
python-multipart==0.0.22
pytz==2026.3.post1
PyWavelets==1.9.0
PyYAML==6.0.3
redis==5.2.0
regex==2026.7.19
requests==2.34.2
rsa==4.9.1
safetensors==0.8.0
scipy==1.18.0
setuptools==75.8.0
six==1.17.0
soupsieve==2.9.1
SQLAlchemy==2.0.46
starlette==0.50.0
structlog==25.5.0
sympy==1.13.1
tokenizers==0.22.2
torch==2.6.0
torchaudio==2.6.0
torchvision==0.21.0
tqdm==4.69.0
transformers==4.57.6
typing-inspection==0.4.2
typing_extensions==4.15.0
tzlocal==5.3.1
urllib3==2.7.0
uvicorn==0.40.0
uvloop==0.22.1
watchfiles==1.1.1
websockets==16.0
yfinance==1.5.2
zxing-cpp==2.3.0