Files
trahn-trade/trahn-trade-backend/internal/api/trade_routes.go
2026-02-22 15:21:18 -05:00

133 lines
3.3 KiB
Go

package api
import (
"fmt"
"net/http"
"github.com/kjannette/trahn-backend/internal/repository"
)
type tradeJSON struct {
T int64 `json:"t"`
Side string `json:"side"`
Price float64 `json:"price"`
Qty float64 `json:"qty"`
GridLevel *int `json:"gridLevel,omitempty"`
USDValue float64 `json:"usdValue"`
IsPaperTrade bool `json:"isPaperTrade"`
}
// parseTradeMode extracts the ?mode= query parameter.
// Returns a *bool: nil = all, true = paper, false = live.
func parseTradeMode(r *http.Request) (*bool, error) {
v := r.URL.Query().Get("mode")
switch v {
case "", "all":
return nil, nil
case "paper":
b := true
return &b, nil
case "live":
b := false
return &b, nil
default:
return nil, fmt.Errorf("invalid mode %q, expected paper|live|all", v)
}
}
func (s *Server) handleTradesToday(w http.ResponseWriter, r *http.Request) {
mode, err := parseTradeMode(r)
if err != nil {
writeError(w, http.StatusBadRequest, err.Error())
return
}
ctx := r.Context()
today := repository.TradingDayNow()
trades, err := s.tradeRepo.GetByDay(ctx, today, mode)
if err != nil {
fmt.Printf("Error fetching today's trades: %v\n", err)
writeError(w, http.StatusInternalServerError, "failed to fetch trades")
return
}
out := make([]tradeJSON, len(trades))
for i, t := range trades {
out[i] = tradeJSON{
T: t.Timestamp.UnixMilli(), Side: t.Side,
Price: t.Price, Qty: t.Quantity,
GridLevel: t.GridLevel, USDValue: t.USDValue,
IsPaperTrade: t.IsPaperTrade,
}
}
writeJSON(w, http.StatusOK, out)
}
func (s *Server) handleTradesByDay(w http.ResponseWriter, r *http.Request) {
date := r.PathValue("date")
if !validateDate(date) {
writeError(w, http.StatusBadRequest, "invalid date format, expected YYYY-MM-DD")
return
}
mode, err := parseTradeMode(r)
if err != nil {
writeError(w, http.StatusBadRequest, err.Error())
return
}
ctx := r.Context()
trades, err := s.tradeRepo.GetByDay(ctx, date, mode)
if err != nil {
fmt.Printf("Error fetching trades for %s: %v\n", date, err)
writeError(w, http.StatusInternalServerError, "failed to fetch trades")
return
}
out := make([]tradeJSON, len(trades))
for i, t := range trades {
out[i] = tradeJSON{
T: t.Timestamp.UnixMilli(), Side: t.Side,
Price: t.Price, Qty: t.Quantity,
GridLevel: t.GridLevel, USDValue: t.USDValue,
IsPaperTrade: t.IsPaperTrade,
}
}
writeJSON(w, http.StatusOK, out)
}
func (s *Server) handleAllTrades(w http.ResponseWriter, r *http.Request) {
limit := parseLimit(r, 100)
mode, err := parseTradeMode(r)
if err != nil {
writeError(w, http.StatusBadRequest, err.Error())
return
}
trades, err := s.tradeRepo.GetAll(r.Context(), limit, mode)
if err != nil {
fmt.Printf("Error fetching all trades: %v\n", err)
writeError(w, http.StatusInternalServerError, "failed to fetch trades")
return
}
writeJSON(w, http.StatusOK, trades)
}
func (s *Server) handleTradeStats(w http.ResponseWriter, r *http.Request) {
mode, err := parseTradeMode(r)
if err != nil {
writeError(w, http.StatusBadRequest, err.Error())
return
}
stats, err := s.tradeRepo.GetStats(r.Context(), mode)
if err != nil {
fmt.Printf("Error fetching trade stats: %v\n", err)
writeError(w, http.StatusInternalServerError, "failed to fetch trade stats")
return
}
writeJSON(w, http.StatusOK, stats)
}