feat(domain/socket): 시장 데이터와 백테스트 소켓에 multi-timeframe 지원을 추가한다
packages/domain/market: timeframemap 타입 추가 및 테스트 services/api/internal/socket/market: multi-timeframe 소켓 메시지 지원 services/worker/internal/socket/backtest_mapping: 백테스트 매핑 함수에 multi-timeframe 반영
This commit is contained in:
parent
7c1e36cefa
commit
9d8dde6dc9
6 changed files with 40 additions and 5 deletions
|
|
@ -30,9 +30,10 @@ const (
|
||||||
type Timeframe string
|
type Timeframe string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
TimeframeDaily Timeframe = "1d"
|
TimeframeMonthly Timeframe = "1mo"
|
||||||
TimeframeMin1 Timeframe = "1m"
|
TimeframeDaily Timeframe = "1d"
|
||||||
TimeframeMin5 Timeframe = "5m"
|
TimeframeMin1 Timeframe = "1m"
|
||||||
|
TimeframeMin5 Timeframe = "5m"
|
||||||
)
|
)
|
||||||
|
|
||||||
type InstrumentID string
|
type InstrumentID string
|
||||||
|
|
|
||||||
|
|
@ -79,6 +79,23 @@ func TestMarketVenueMetadata(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestTimeframeVocabulary(t *testing.T) {
|
||||||
|
cases := []struct {
|
||||||
|
timeframe Timeframe
|
||||||
|
want string
|
||||||
|
}{
|
||||||
|
{TimeframeMonthly, "1mo"},
|
||||||
|
{TimeframeDaily, "1d"},
|
||||||
|
{TimeframeMin1, "1m"},
|
||||||
|
{TimeframeMin5, "5m"},
|
||||||
|
}
|
||||||
|
for _, c := range cases {
|
||||||
|
if string(c.timeframe) != c.want {
|
||||||
|
t.Errorf("timeframe %q: got %q, want %q", c.want, string(c.timeframe), c.want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestProviderCapabilityRequireDailyBars(t *testing.T) {
|
func TestProviderCapabilityRequireDailyBars(t *testing.T) {
|
||||||
// A KIS-like capability serving both KR and US daily bars.
|
// A KIS-like capability serving both KR and US daily bars.
|
||||||
kis := ProviderCapability{
|
kis := ProviderCapability{
|
||||||
|
|
|
||||||
|
|
@ -207,7 +207,7 @@ func validateImportDateRange(fromValue, toValue string) error {
|
||||||
|
|
||||||
func isValidTimeframe(t altv1.Timeframe) bool {
|
func isValidTimeframe(t altv1.Timeframe) bool {
|
||||||
switch t {
|
switch t {
|
||||||
case altv1.Timeframe_TIMEFRAME_DAILY, altv1.Timeframe_TIMEFRAME_MINUTE_1, altv1.Timeframe_TIMEFRAME_MINUTE_5:
|
case altv1.Timeframe_TIMEFRAME_MONTHLY, altv1.Timeframe_TIMEFRAME_DAILY, altv1.Timeframe_TIMEFRAME_MINUTE_1, altv1.Timeframe_TIMEFRAME_MINUTE_5:
|
||||||
return true
|
return true
|
||||||
default:
|
default:
|
||||||
return false
|
return false
|
||||||
|
|
|
||||||
|
|
@ -167,6 +167,19 @@ func TestHandleListBarsValidation(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestIsValidTimeframeAcceptsMonthlyAndMinuteBaseline(t *testing.T) {
|
||||||
|
for _, tf := range []altv1.Timeframe{
|
||||||
|
altv1.Timeframe_TIMEFRAME_MONTHLY,
|
||||||
|
altv1.Timeframe_TIMEFRAME_DAILY,
|
||||||
|
altv1.Timeframe_TIMEFRAME_MINUTE_1,
|
||||||
|
altv1.Timeframe_TIMEFRAME_MINUTE_5,
|
||||||
|
} {
|
||||||
|
if !isValidTimeframe(tf) {
|
||||||
|
t.Errorf("expected timeframe %v to be valid", tf)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestHandleListBarsNilWorker(t *testing.T) {
|
func TestHandleListBarsNilWorker(t *testing.T) {
|
||||||
resp, err := handleListBars(nil, validBarsRequest())
|
resp, err := handleListBars(nil, validBarsRequest())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -102,6 +102,8 @@ func marketToProto(m market.Market) altv1.Market {
|
||||||
|
|
||||||
func timeframeFromProto(t altv1.Timeframe) (market.Timeframe, error) {
|
func timeframeFromProto(t altv1.Timeframe) (market.Timeframe, error) {
|
||||||
switch t {
|
switch t {
|
||||||
|
case altv1.Timeframe_TIMEFRAME_MONTHLY:
|
||||||
|
return market.TimeframeMonthly, nil
|
||||||
case altv1.Timeframe_TIMEFRAME_DAILY:
|
case altv1.Timeframe_TIMEFRAME_DAILY:
|
||||||
return market.TimeframeDaily, nil
|
return market.TimeframeDaily, nil
|
||||||
case altv1.Timeframe_TIMEFRAME_MINUTE_1:
|
case altv1.Timeframe_TIMEFRAME_MINUTE_1:
|
||||||
|
|
@ -115,6 +117,8 @@ func timeframeFromProto(t altv1.Timeframe) (market.Timeframe, error) {
|
||||||
|
|
||||||
func timeframeToProto(t market.Timeframe) altv1.Timeframe {
|
func timeframeToProto(t market.Timeframe) altv1.Timeframe {
|
||||||
switch t {
|
switch t {
|
||||||
|
case market.TimeframeMonthly:
|
||||||
|
return altv1.Timeframe_TIMEFRAME_MONTHLY
|
||||||
case market.TimeframeDaily:
|
case market.TimeframeDaily:
|
||||||
return altv1.Timeframe_TIMEFRAME_DAILY
|
return altv1.Timeframe_TIMEFRAME_DAILY
|
||||||
case market.TimeframeMin1:
|
case market.TimeframeMin1:
|
||||||
|
|
|
||||||
|
|
@ -92,7 +92,7 @@ func TestMarketEnumRoundTrip(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTimeframeEnumRoundTrip(t *testing.T) {
|
func TestTimeframeEnumRoundTrip(t *testing.T) {
|
||||||
for _, tf := range []market.Timeframe{market.TimeframeDaily, market.TimeframeMin1, market.TimeframeMin5} {
|
for _, tf := range []market.Timeframe{market.TimeframeMonthly, market.TimeframeDaily, market.TimeframeMin1, market.TimeframeMin5} {
|
||||||
got, err := timeframeFromProto(timeframeToProto(tf))
|
got, err := timeframeFromProto(timeframeToProto(tf))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error for %q: %v", tf, err)
|
t.Fatalf("unexpected error for %q: %v", tf, err)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue