Files
overnight-trading-bot/internal/instruments/registry.go
T
Valentin Popov f877907b20
Deploy / Test, build and deploy (push) Successful in 50s
twelve version
2026-06-08 20:11:10 +00:00

71 lines
2.4 KiB
Go

package instruments
import (
"context"
"fmt"
"overnight-trading-bot/internal/domain"
"overnight-trading-bot/internal/repository"
"overnight-trading-bot/internal/tinvest"
)
type Registry struct {
repo repository.Repository
gateway tinvest.Gateway
}
func NewRegistry(repo repository.Repository, gateway tinvest.Gateway) Registry {
return Registry{repo: repo, gateway: gateway}
}
func (r Registry) SyncMetadata(ctx context.Context) error {
instruments, err := r.repo.ListInstruments(ctx, true)
if err != nil {
return err
}
for _, instrument := range instruments {
if !instrument.Enabled || instrument.Quarantine {
continue
}
remote, err := r.gateway.GetInstrument(ctx, instrument.Ticker, instrument.ClassCode)
if err != nil {
if insertErr := r.repo.InsertRiskEvent(ctx, domain.RiskEvent{
Severity: domain.SeverityWarn,
EventType: "instrument_metadata_sync_failed",
InstrumentUID: instrument.InstrumentUID,
Message: fmt.Sprintf("sync instrument metadata %s: %s", instrument.Ticker, err),
ContextJSON: fmt.Sprintf(`{"ticker":%q,"class_code":%q}`, instrument.Ticker, instrument.ClassCode),
}); insertErr != nil {
return fmt.Errorf("record metadata sync failure %s: %w", instrument.Ticker, insertErr)
}
continue
}
remote.Enabled = instrument.Enabled && remote.Enabled
remote.FundType = instrument.FundType
remote.ExpectedCommissionBpsPerSide = instrument.ExpectedCommissionBpsPerSide
remote.FreeOrderLimitPerDay = instrument.FreeOrderLimitPerDay
remote.Quarantine = instrument.Quarantine
remote.QuarantineReason = instrument.QuarantineReason
remote.ExcludeReason = instrument.ExcludeReason
if err := r.repo.ReplaceInstrument(ctx, instrument.InstrumentUID, remote); err != nil {
return fmt.Errorf("replace synced instrument %s: %w", instrument.Ticker, err)
}
}
return nil
}
func CheckInstrument(instrument domain.Instrument, status domain.TradingStatus) error {
switch {
case !instrument.Enabled:
return fmt.Errorf("%s disabled", instrument.Ticker)
case instrument.Quarantine:
return fmt.Errorf("%s quarantined: %s", instrument.Ticker, instrument.QuarantineReason)
case !instrument.MetadataValid():
return fmt.Errorf("%s invalid metadata", instrument.Ticker)
case status != domain.TradingStatusNormal:
return fmt.Errorf("%s trading status %s", instrument.Ticker, status)
default:
return nil
}
}