alt/services/worker/internal/socket/market_mapping.go
toki f552dfc3ef feat: US market expansion & asset type instrument support
- Add asset_type column to instrument table (migration 000003)
- Extend market domain types with asset_type and related fields
- Update proto definitions for common and market messages
- Regenerate Dart and Go protobuf code
- Add shared query surface for US market data
- Add KIS US daily itemchartprice provider and tests
- Update backtest and operator components for US market support
- Update socket market mapping for new asset types
- Move paper-trading-command-workflow to archive
- Add agent-task for m-us-market-expansion (subtasks 02+01, 03+01, 04+02,03)
2026-06-06 15:56:21 +09:00

116 lines
3.1 KiB
Go

package socket
import (
"fmt"
altv1 "git.toki-labs.com/toki/alt/packages/contracts/gen/go/alt/v1"
"git.toki-labs.com/toki/alt/packages/domain/market"
)
func instrumentToProto(inst market.Instrument) *altv1.Instrument {
return &altv1.Instrument{
Id: string(inst.ID),
Market: marketToProto(inst.Market),
Venue: venueToProto(inst.Venue),
Symbol: inst.Symbol,
Name: inst.Name,
Currency: currencyToProto(inst.Currency),
ProviderSymbols: cloneProviderSymbols(inst.ProviderSymbols),
AssetType: assetTypeToProto(inst.AssetType),
}
}
func assetTypeToProto(at market.AssetType) altv1.AssetType {
switch at {
case market.AssetTypeEquity:
return altv1.AssetType_ASSET_TYPE_EQUITY
case market.AssetTypeETF:
return altv1.AssetType_ASSET_TYPE_ETF
default:
return altv1.AssetType_ASSET_TYPE_UNSPECIFIED
}
}
func assetTypeFromProto(at altv1.AssetType) (market.AssetType, error) {
switch at {
case altv1.AssetType_ASSET_TYPE_UNSPECIFIED:
return "", nil
case altv1.AssetType_ASSET_TYPE_EQUITY:
return market.AssetTypeEquity, nil
case altv1.AssetType_ASSET_TYPE_ETF:
return market.AssetTypeETF, nil
default:
return "", fmt.Errorf("unsupported asset type %q", at.String())
}
}
func instrumentsToProto(insts []market.Instrument) []*altv1.Instrument {
out := make([]*altv1.Instrument, len(insts))
for i, inst := range insts {
out[i] = instrumentToProto(inst)
}
return out
}
func barToProto(bar market.Bar) *altv1.Bar {
return &altv1.Bar{
InstrumentId: string(bar.InstrumentID),
Timeframe: timeframeToProto(bar.Timeframe),
TimestampUnixMs: timeToUnixMs(bar.Timestamp),
Open: priceToProto(bar.Open),
High: priceToProto(bar.High),
Low: priceToProto(bar.Low),
Close: priceToProto(bar.Close),
Volume: quantityToProto(bar.Volume),
}
}
func barsToProto(bars []market.Bar) []*altv1.Bar {
out := make([]*altv1.Bar, len(bars))
for i, bar := range bars {
out[i] = barToProto(bar)
}
return out
}
// venueFromProto converts a proto venue to the domain venue. The unspecified
// venue maps to an empty domain venue because an import selector may not pin a
// venue (e.g. a watchlist selector); only out-of-range enum values are an error.
func venueFromProto(v altv1.Venue) (market.Venue, error) {
switch v {
case altv1.Venue_VENUE_UNSPECIFIED:
return "", nil
case altv1.Venue_VENUE_KRX:
return market.VenueKRX, nil
case altv1.Venue_VENUE_NASDAQ:
return market.VenueNASDAQ, nil
case altv1.Venue_VENUE_NYSE:
return market.VenueNYSE, nil
default:
return "", fmt.Errorf("unsupported venue %q", v.String())
}
}
func venueToProto(v market.Venue) altv1.Venue {
switch v {
case market.VenueKRX:
return altv1.Venue_VENUE_KRX
case market.VenueNASDAQ:
return altv1.Venue_VENUE_NASDAQ
case market.VenueNYSE:
return altv1.Venue_VENUE_NYSE
default:
return altv1.Venue_VENUE_UNSPECIFIED
}
}
func cloneProviderSymbols(symbols map[string]string) map[string]string {
if len(symbols) == 0 {
return nil
}
out := make(map[string]string, len(symbols))
for k, v := range symbols {
out[k] = v
}
return out
}