feat: add portfolio

This commit is contained in:
ytshih committed 2026-09-11 09:54:49 +08:00
1 parent ba63c5deb0
commit f09cf4d5c2
11 files changed
+669 -38

No files matched your search

+57 -4
View File
@@ -4,15 +4,68 @@ package report
// Recommendation is a single buy/sell call with a short reason, surfaced
// separately from the main narrative report (e.g. as a Discord embed).
//
// AmountUSD and Leverage are Claude's requested position size and leverage —
// a decision, not a calculation. The actual quantity, margin, and any
// resulting profit/loss are computed deterministically by internal/portfolio
// from the fetched price at execution time, never by Claude; Go also clamps
// AmountUSD to available cash and Leverage to the configured maximum, so
// these fields are a request, not a guarantee of what was executed (see
// PortfolioSnapshot.Trades for what actually happened).
type Recommendation struct {
Symbol string `json:"symbol"`
Action string `json:"action"` // "buy" or "sell"
Reason string `json:"reason"`
Symbol string `json:"symbol"`
Action string `json:"action"` // "buy" or "sell"
Reason string `json:"reason"`
AmountUSD float64 `json:"amount_usd"` // requested USD margin to commit, before leverage
Leverage float64 `json:"leverage"` // requested leverage multiplier, e.g. 1 = no leverage
}
// Position is one open, leveraged paper-trading position, marked to market
// at the current fetched price.
type Position struct {
Symbol string
Side string // "long" or "short"
Quantity float64
EntryPrice float64
CurrentPrice float64
Margin float64 // USD committed, before leverage
Leverage float64
UnrealizedPnL float64
}
// TradeExecution records what internal/portfolio actually did with one
// Recommendation at fetch-time prices — which may differ from what was
// requested (e.g. clamped to available cash, or skipped entirely).
type TradeExecution struct {
Symbol string
Action string
Price float64 // fetch-time price the trade executed at
AmountUSD float64 // USD margin actually committed
Leverage float64 // leverage actually applied
Executed bool
Note string // what happened, or why it was skipped
RealizedPnL float64
}
// PortfolioSnapshot is the paper-trading portfolio's state after applying
// this run's trades, computed entirely by internal/portfolio — never by
// Claude — from the fetched prices.
type PortfolioSnapshot struct {
InitialBudgetUSD float64
CashUSD float64
EquityUSD float64 // cash + margin + unrealized P&L of all open positions
TotalProfitUSD float64 // EquityUSD - InitialBudgetUSD
TotalProfitPct float64
Positions []Position
Trades []TradeExecution // this run's executions
}
// Report is the full output of one analysis run: the long-form narrative
// text plus an optional short list of buy/sell recommendations.
// text, an optional short list of buy/sell recommendations, the resulting
// portfolio state, and Claude's freeform memory notes for future runs.
type Report struct {
Text string
Recommendations []Recommendation
Portfolio PortfolioSnapshot
Memory string
}