fix: db migration tab char corrupted, restore historical trades

This commit is contained in:
jackyu66git
2026-05-04 13:50:49 +08:00
parent e74fd084ce
commit f29e78a435
5 changed files with 264 additions and 58 deletions
+12
View File
@@ -113,6 +113,18 @@ func (d *DB) migrate() error {
if err != nil {
return err
}
// Migration v2: add per-exchange fee/pnl columns (idempotent)
for _, col := range []string{"pnl_long_usd", "pnl_short_usd", "fee_long_usd", "fee_short_usd"} {
var found int
d.QueryRow("SELECT COUNT(*) FROM pragma_table_info('trades') WHERE name=?", col).Scan(&found)
if found == 0 {
if _, err := d.Exec("ALTER TABLE trades ADD COLUMN " + col + " REAL"); err != nil {
log.Printf("[DB] Migration: add column %s: %v", col, err)
}
}
}
log.Printf("[DB] SQLite ready: %s", d.Path)
return nil
}
+21 -7
View File
@@ -30,6 +30,10 @@ type TradeRecord struct {
Convergence *string
OpenedAt time.Time
ClosedAt *time.Time
PnlLongUSD *float64 // per-exchange PnL in USD
PnlShortUSD *float64
FeeLongUSD *float64 // per-exchange fee in USD
FeeShortUSD *float64
}
// OrderRecord mirrors the database row for orders table.
@@ -68,12 +72,14 @@ func (d *DB) SaveTrade(t *TradeRecord) (int64, error) {
coin, direction, status, entry_spread, exit_spread,
long_exchange, short_exchange, long_entry, long_exit, short_entry, short_exit,
long_pnl, short_pnl, fee_entry, fee_exit, net_pnl,
amount_usd, scale_count, exit_reason, convergence, opened_at, closed_at
) VALUES (?,?,?,?,?, ?,?,?,?,?, ?,?,?,?,?, ?,?,?,?,?, ?,?)`,
amount_usd, scale_count, exit_reason, convergence, opened_at, closed_at,
pnl_long_usd, pnl_short_usd, fee_long_usd, fee_short_usd
) VALUES (?,?,?,?,?, ?,?,?,?,?, ?,?,?,?,?, ?,?,?,?,?, ?,?,?,?,?)`,
t.Coin, t.Direction, t.Status, t.EntrySpread, t.ExitSpread,
t.LongExchange, t.ShortExchange, t.LongEntry, t.LongExit, t.ShortEntry, t.ShortExit,
t.LongPnl, t.ShortPnl, t.FeeEntry, t.FeeExit, t.NetPnl,
t.AmountUSD, t.ScaleCount, t.ExitReason, t.Convergence, t.OpenedAt, t.ClosedAt,
t.PnlLongUSD, t.PnlShortUSD, t.FeeLongUSD, t.FeeShortUSD,
)
if err != nil {
return 0, err
@@ -86,12 +92,14 @@ func (d *DB) UpdateTradeStatus(id int64, t *TradeRecord) error {
_, err := d.Exec(`UPDATE trades SET
status=?, exit_spread=?, long_exit=?, short_exit=?,
long_pnl=?, short_pnl=?, fee_entry=?, fee_exit=?, net_pnl=?,
amount_usd=?, scale_count=?, exit_reason=?, convergence=?, closed_at=?
amount_usd=?, scale_count=?, exit_reason=?, convergence=?, closed_at=?,
pnl_long_usd=?, pnl_short_usd=?, fee_long_usd=?, fee_short_usd=?
WHERE id=?`,
t.Status, t.ExitSpread,
t.LongExit, t.ShortExit,
t.LongPnl, t.ShortPnl, t.FeeEntry, t.FeeExit, t.NetPnl,
t.AmountUSD, t.ScaleCount, t.ExitReason, t.Convergence, t.ClosedAt,
t.PnlLongUSD, t.PnlShortUSD, t.FeeLongUSD, t.FeeShortUSD,
id,
)
return err
@@ -102,7 +110,8 @@ func (d *DB) GetOpenTrades() ([]TradeRecord, error) {
rows, err := d.Query(`SELECT id, coin, direction, status, entry_spread, exit_spread,
long_exchange, short_exchange, long_entry, long_exit, short_entry, short_exit,
long_pnl, short_pnl, fee_entry, fee_exit, net_pnl,
amount_usd, scale_count, exit_reason, convergence, opened_at, closed_at
amount_usd, scale_count, exit_reason, convergence, opened_at, closed_at,
pnl_long_usd, pnl_short_usd, fee_long_usd, fee_short_usd
FROM trades WHERE status='open'`)
if err != nil {
return nil, err
@@ -130,7 +139,8 @@ func (d *DB) GetTrades(page, limit int, coin string) ([]TradeRecord, int, error)
query := `SELECT id, coin, direction, status, entry_spread, exit_spread,
long_exchange, short_exchange, long_entry, long_exit, short_entry, short_exit,
long_pnl, short_pnl, fee_entry, fee_exit, net_pnl,
amount_usd, scale_count, exit_reason, convergence, opened_at, closed_at
amount_usd, scale_count, exit_reason, convergence, opened_at, closed_at,
pnl_long_usd, pnl_short_usd, fee_long_usd, fee_short_usd
FROM trades WHERE status='closed'`
if coin != "" {
query += " AND coin=?"
@@ -183,7 +193,8 @@ func (d *DB) GetTradeByID(id int64) (*TradeRecord, []OrderRecord, error) {
row := d.QueryRow(`SELECT id, coin, direction, status, entry_spread, exit_spread,
long_exchange, short_exchange, long_entry, long_exit, short_entry, short_exit,
long_pnl, short_pnl, fee_entry, fee_exit, net_pnl,
amount_usd, scale_count, exit_reason, convergence, opened_at, closed_at
amount_usd, scale_count, exit_reason, convergence, opened_at, closed_at,
pnl_long_usd, pnl_short_usd, fee_long_usd, fee_short_usd
FROM trades WHERE id=?`, id)
var t TradeRecord
@@ -192,6 +203,7 @@ func (d *DB) GetTradeByID(id int64) (*TradeRecord, []OrderRecord, error) {
&t.LongExchange, &t.ShortExchange, &t.LongEntry, &t.LongExit, &t.ShortEntry, &t.ShortExit,
&t.LongPnl, &t.ShortPnl, &t.FeeEntry, &t.FeeExit, &t.NetPnl,
&t.AmountUSD, &t.ScaleCount, &t.ExitReason, &t.Convergence, &t.OpenedAt, &t.ClosedAt,
&t.PnlLongUSD, &t.PnlShortUSD, &t.FeeLongUSD, &t.FeeShortUSD,
)
if err != nil {
return nil, nil, err
@@ -227,6 +239,7 @@ func scanTrades(rows *sql.Rows) ([]TradeRecord, error) {
&t.LongExchange, &t.ShortExchange, &t.LongEntry, &t.LongExit, &t.ShortEntry, &t.ShortExit,
&t.LongPnl, &t.ShortPnl, &t.FeeEntry, &t.FeeExit, &t.NetPnl,
&t.AmountUSD, &t.ScaleCount, &t.ExitReason, &t.Convergence, &t.OpenedAt, &t.ClosedAt,
&t.PnlLongUSD, &t.PnlShortUSD, &t.FeeLongUSD, &t.FeeShortUSD,
); err != nil {
return nil, err
}
@@ -265,7 +278,8 @@ func (d *DB) GetAllClosedTrades() ([]TradeRecord, error) {
rows, err := d.Query(`SELECT id, coin, direction, status, entry_spread, exit_spread,
long_exchange, short_exchange, long_entry, long_exit, short_entry, short_exit,
long_pnl, short_pnl, fee_entry, fee_exit, net_pnl,
amount_usd, scale_count, exit_reason, convergence, opened_at, closed_at
amount_usd, scale_count, exit_reason, convergence, opened_at, closed_at,
pnl_long_usd, pnl_short_usd, fee_long_usd, fee_short_usd
FROM trades WHERE status='closed' ORDER BY id`)
if err != nil {
return nil, err