mirror of
https://github.com/tiennm99/miti99bot.git
synced 2026-07-28 14:21:23 +00:00
Rename the `trading` module to `stock` across code, config, and docs for naming consistency with the sibling coin/gold modules. - Module: internal/modules/trading -> internal/modules/stock (package, factory, registry key in cmd/server) - Commands: trade_* -> stock_* (telegram-commands.json) - Env/SAM params: TRADING_INCOME_EVENTS_* -> STOCK_INCOME_EVENTS_* - ModulesCSV updated in template.yaml, samconfig.toml, deploy.yml - Add cmd/migrate-stock-key: idempotent, non-destructive DynamoDB partition copy (pk=trading -> pk=stock) with dry-run default Production DynamoDB data already migrated (8 keys: 2 portfolios + 6 symbol-cache rows); old trading partition retained as rollback snapshot.
60 lines
1.5 KiB
Go
60 lines
1.5 KiB
Go
// Package stock is a paper-stock module for VN stocks. Per-user
|
|
// portfolio + buy/sell at market price + stats with P&L. SQL-based trade
|
|
// history and a retention cron are out of scope today; the current
|
|
// implementation keeps only the live portfolio in KV.
|
|
package stock
|
|
|
|
import (
|
|
"math"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
// FormatVND renders an integer-rounded amount with dot-thousands separators
|
|
// and a "VND" suffix (e.g. 15000000 -> "15.000.000 VND"). Manual to avoid
|
|
// locale-dependent formatting.
|
|
func FormatVND(n float64) string {
|
|
rounded := int64(math.Round(n))
|
|
abs := strconv.FormatInt(absInt64(rounded), 10)
|
|
var sb strings.Builder
|
|
if rounded < 0 {
|
|
sb.WriteByte('-')
|
|
}
|
|
for i := 0; i < len(abs); i++ {
|
|
if i > 0 && (len(abs)-i)%3 == 0 {
|
|
sb.WriteByte('.')
|
|
}
|
|
sb.WriteByte(abs[i])
|
|
}
|
|
sb.WriteString(" VND")
|
|
return sb.String()
|
|
}
|
|
|
|
// FormatStock renders an integer share quantity (always whole shares).
|
|
func FormatStock(n float64) string {
|
|
return strconv.FormatInt(int64(math.Floor(n)), 10)
|
|
}
|
|
|
|
// FormatPnL renders a signed VND delta + percentage line, e.g.
|
|
// "+1.234 VND (+12.34%)" or "-500.000 VND (-5.00%)". When invested is zero
|
|
// the percentage is reported as 0.00 to avoid division-by-zero.
|
|
func FormatPnL(currentValue, invested float64) string {
|
|
diff := currentValue - invested
|
|
pct := 0.0
|
|
if invested > 0 {
|
|
pct = (diff / invested) * 100
|
|
}
|
|
sign := ""
|
|
if diff >= 0 {
|
|
sign = "+"
|
|
}
|
|
return sign + FormatVND(diff) + " (" + sign + strconv.FormatFloat(pct, 'f', 2, 64) + "%)"
|
|
}
|
|
|
|
func absInt64(n int64) int64 {
|
|
if n < 0 {
|
|
return -n
|
|
}
|
|
return n
|
|
}
|