mirror of
https://github.com/wahyd4/links.git
synced 2026-08-09 05:06:16 +10:00
- Portfolio management (MOMO, IBKR personal, IBKR Yanhua) - Stock holdings with transaction history (buy/sell) - Weekly AI report generation - Real-time price cache via Finnhub API - Dashboard with tree view and performance charts - REST API with AI-friendly batch update endpoint - Management command for scheduled report generation For大哥's personal investment advisor system.
81 lines
2.6 KiB
Python
81 lines
2.6 KiB
Python
"""Template views for the invest app."""
|
|
import json
|
|
import logging
|
|
|
|
from django.shortcuts import render, get_object_or_404
|
|
|
|
from .models import Portfolio, Report
|
|
from .services import portfolio_summary
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def dashboard(request):
|
|
"""Landing page: list of portfolios with key metrics."""
|
|
portfolios = Portfolio.objects.prefetch_related('stocks').order_by('name')
|
|
summaries = []
|
|
for portfolio in portfolios:
|
|
try:
|
|
s = portfolio_summary(portfolio)
|
|
except Exception as exc:
|
|
logger.warning("portfolio_summary failed for %s: %s", portfolio.id, exc)
|
|
s = {
|
|
'portfolio': {'id': portfolio.id, 'name': portfolio.name},
|
|
'stocks': [],
|
|
'total_cost': 0,
|
|
'total_market_value': 0,
|
|
'total_unrealized_pnl': 0,
|
|
'total_unrealized_pnl_pct': 0,
|
|
}
|
|
summaries.append(s)
|
|
|
|
return render(request, 'invest/dashboard.html', {'summaries': summaries})
|
|
|
|
|
|
def portfolio_detail(request, pk):
|
|
"""Portfolio detail view with holdings table and allocation chart."""
|
|
portfolio = get_object_or_404(Portfolio, pk=pk)
|
|
try:
|
|
summary = portfolio_summary(portfolio)
|
|
except Exception as exc:
|
|
logger.error("portfolio_summary failed for %s: %s", pk, exc)
|
|
summary = {
|
|
'portfolio': {'id': portfolio.id, 'name': portfolio.name},
|
|
'stocks': [],
|
|
'total_cost': 0,
|
|
'total_market_value': 0,
|
|
'total_unrealized_pnl': 0,
|
|
'total_unrealized_pnl_pct': 0,
|
|
}
|
|
return render(request, 'invest/portfolio_detail.html', {
|
|
'portfolio': portfolio,
|
|
'summary': summary,
|
|
'summary_json': json.dumps(summary),
|
|
})
|
|
|
|
|
|
def portfolio_transactions(request, pk):
|
|
"""Transaction history for a portfolio."""
|
|
from .models import Transaction
|
|
portfolio = get_object_or_404(Portfolio, pk=pk)
|
|
transactions = Transaction.objects.filter(
|
|
stock__portfolio=portfolio
|
|
).select_related('stock').order_by('-date', '-created_at')
|
|
|
|
return render(request, 'invest/transactions.html', {
|
|
'portfolio': portfolio,
|
|
'transactions': transactions,
|
|
})
|
|
|
|
|
|
def reports_list(request):
|
|
"""List of all generated reports."""
|
|
reports = Report.objects.select_related('portfolio').order_by('-generated_at')
|
|
return render(request, 'invest/reports.html', {'reports': reports})
|
|
|
|
|
|
def report_detail(request, pk):
|
|
"""Single report view."""
|
|
report = get_object_or_404(Report.objects.select_related('portfolio'), pk=pk)
|
|
return render(request, 'invest/report_detail.html', {'report': report})
|