Files
aitrade/pkg/db/positions.go
T
kaedwen ea141eb012
Build and Push Docker Image / build-and-push (push) Failing after 1m41s
initial
2026-07-02 20:09:44 +02:00

155 lines
3.3 KiB
Go

package db
import (
"context"
"database/sql"
"fmt"
"time"
"github.com/pheinrich/aitrade/pkg/model"
)
type PositionRepository struct {
db Database
}
func NewPositionRepository(db Database) *PositionRepository {
return &PositionRepository{db: db}
}
func (r *PositionRepository) Create(ctx context.Context, position *model.Position) error {
query := `
INSERT INTO positions (symbol, quantity, entry_price, entry_trade_id, opened_at, updated_at)
VALUES (?, ?, ?, ?, ?, ?)
`
now := time.Now()
result, err := r.db.ExecContext(ctx, query,
position.Symbol,
position.Quantity,
position.EntryPrice,
position.EntryTradeID,
now,
now,
)
if err != nil {
return fmt.Errorf("failed to insert position: %w", err)
}
id, err := result.LastInsertId()
if err != nil {
return fmt.Errorf("failed to get last insert id: %w", err)
}
position.ID = id
position.OpenedAt = now
position.UpdatedAt = now
return nil
}
func (r *PositionRepository) Update(ctx context.Context, position *model.Position) error {
query := `
UPDATE positions SET
current_price = ?,
unrealized_pnl = ?,
updated_at = ?
WHERE id = ?
`
now := time.Now()
_, err := r.db.ExecContext(ctx, query,
position.CurrentPrice,
position.UnrealizedPnL,
now,
position.ID,
)
if err != nil {
return fmt.Errorf("failed to update position: %w", err)
}
position.UpdatedAt = now
return nil
}
func (r *PositionRepository) Delete(ctx context.Context, id int64) error {
query := `DELETE FROM positions WHERE id = ?`
_, err := r.db.ExecContext(ctx, query, id)
if err != nil {
return fmt.Errorf("failed to delete position: %w", err)
}
return nil
}
func (r *PositionRepository) GetBySymbol(ctx context.Context, symbol string) (*model.Position, error) {
query := `
SELECT id, symbol, quantity, entry_price, entry_trade_id, current_price, unrealized_pnl, opened_at, updated_at
FROM positions
WHERE symbol = ?
`
var position model.Position
err := r.db.QueryRowContext(ctx, query, symbol).Scan(
&position.ID,
&position.Symbol,
&position.Quantity,
&position.EntryPrice,
&position.EntryTradeID,
&position.CurrentPrice,
&position.UnrealizedPnL,
&position.OpenedAt,
&position.UpdatedAt,
)
if err == sql.ErrNoRows {
return nil, nil // No position found
}
if err != nil {
return nil, fmt.Errorf("failed to get position: %w", err)
}
return &position, nil
}
func (r *PositionRepository) GetAll(ctx context.Context) ([]*model.Position, error) {
query := `
SELECT id, symbol, quantity, entry_price, entry_trade_id, current_price, unrealized_pnl, opened_at, updated_at
FROM positions
ORDER BY opened_at DESC
`
rows, err := r.db.QueryContext(ctx, query)
if err != nil {
return nil, fmt.Errorf("failed to query positions: %w", err)
}
defer rows.Close()
var positions []*model.Position
for rows.Next() {
var position model.Position
if err := rows.Scan(
&position.ID,
&position.Symbol,
&position.Quantity,
&position.EntryPrice,
&position.EntryTradeID,
&position.CurrentPrice,
&position.UnrealizedPnL,
&position.OpenedAt,
&position.UpdatedAt,
); err != nil {
return nil, fmt.Errorf("failed to scan position: %w", err)
}
positions = append(positions, &position)
}
if err := rows.Err(); err != nil {
return nil, fmt.Errorf("error iterating position rows: %w", err)
}
return positions, nil
}