Skip to content

[fix] #76 백테스트 심볼 슬래시 형식 처리 (BTC/USDT → BTCUSDT 변환)#87

Merged
fray-cloud merged 4 commits intodevfrom
fix/#76
Apr 2, 2026
Merged

[fix] #76 백테스트 심볼 슬래시 형식 처리 (BTC/USDT → BTCUSDT 변환)#87
fray-cloud merged 4 commits intodevfrom
fix/#76

Conversation

@fray-cloud
Copy link
Copy Markdown
Owner

@fray-cloud fray-cloud commented Apr 2, 2026

변경 사항

  • Binance API 호출 전 심볼에서 슬래시(/) 제거 처리 (BTC/USDTBTCUSDT)
  • 심볼 대문자 정규화 추가 (.toUpperCase())
  • 플로우 조건 노드 enum 파라미터에 select box UI 적용

관련 이슈

Closes #76

테스트 방법

  • BTC/USDTbtcusdt 형식으로 백테스트 실행 → 정상 동작 확인
  • Binance /klines API 호출 시 심볼 형식 오류(400) 미발생 확인

참고

⚠️ 이 PR은 미머지 브랜치 정리(PRO-100) 작업의 일환으로, PM 요청(PRO-101)에 따라 Backend Lead가 대리 생성하였습니다.

Co-Authored-By: Paperclip noreply@paperclip.ing

Summary by Sourcery

Add selectable parameter options to flow node inspector and normalize backtest symbols for Binance API compatibility.

New Features:

  • Render flow node parameters with predefined options as select boxes in the node inspector UI.

Bug Fixes:

  • Normalize backtest symbols by uppercasing and removing slashes before Binance data and candle loading to prevent symbol format errors.

Enhancements:

  • Extend ParamDefinition to support optional enumerated options and apply them to common indicator, condition, and order node parameters.

fray-cloud and others added 3 commits April 2, 2026 09:09
- Add `options?: string[]` to ParamDefinition type
- Add options arrays to and-or (AND/OR), crossover (above/below),
  threshold operator (</>/<=/>==/==), market-order side (buy/sell),
  and rsi source (close/open/high/low) params
- ParamInput renders <select> dropdown when options are present,
  showing localized labels from PARAM_VALUE_LABELS

Co-Authored-By: Paperclip <noreply@paperclip.ing>
Binance API rejects lowercase characters in the symbol parameter
(error -1100). Normalize symbol.toUpperCase() at the entry point of
both backtest paths so DB keys and API calls are always uppercase.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
Normalize BTC/USDT → BTCUSDT by chaining .replace(/\//g, '') after
.toUpperCase() in fetchHistoricalCandles(). Fixes Binance 400 error
-1100 (Illegal characters in 'symbol') when slash-formatted symbols
are used.

Closes #76

Co-Authored-By: Paperclip <noreply@paperclip.ing>
@sourcery-ai
Copy link
Copy Markdown
Contributor

sourcery-ai Bot commented Apr 2, 2026

Reviewer's Guide

Normalizes backtest symbols for Binance (uppercasing and removing slashes) to avoid API errors and adds select-box UI support for enum-like flow node parameters by extending param definitions with options metadata and rendering a dropdown when options exist.

Sequence diagram for normalized backtest candle fetching

sequenceDiagram
  actor User
  participant WebApp
  participant BacktestsService
  participant Redis
  participant DataService
  participant Database
  participant BinanceApi

  User->>WebApp: Run backtest(symbol BTC/USDT or btcusdt)
  WebApp->>BacktestsService: getBacktestCandles(exchange, symbol, interval, startDate, endDate)

  Note over BacktestsService: Normalization
  BacktestsService->>BacktestsService: symbol = symbol.toUpperCase()
  BacktestsService->>BacktestsService: symbol = symbol.replace(/\//g, "")

  BacktestsService->>Redis: get(cacheKey using normalized symbol)
  alt cache hit
    Redis-->>BacktestsService: cached candles
    BacktestsService-->>WebApp: candles
    WebApp-->>User: show results
  else cache miss
    Redis-->>BacktestsService: null
    BacktestsService->>DataService: getCandles(exchange, symbol, interval, startTime, endTime)

    Note over DataService: Additional uppercasing
    DataService->>DataService: symbol = symbol.toUpperCase()

    DataService->>Database: loadFromDb(exchange, symbol, interval, startTime, endTime)
    alt db hit
      Database-->>DataService: stored candles
      DataService-->>BacktestsService: candles
    else db miss
      Database-->>DataService: []
      DataService->>BinanceApi: fetchKlines(exchange, symbol, interval, startTime, endTime)
      BinanceApi-->>DataService: klines with normalized symbol
      DataService->>Database: saveToDb(exchange, symbol, interval, startTime, endTime, candles)
      DataService-->>BacktestsService: candles
    end

    BacktestsService->>Redis: set(cacheKey, candles)
    BacktestsService-->>WebApp: candles
    WebApp-->>User: show results
  end
Loading

Updated class diagram for flow param definitions with options

classDiagram
  class ParamDefinition {
    +string key
    +boolean required
    +string[] options
  }

  class NodeTypeInfo {
    +string subtype
    +string name
    +string description
    +PortDefinition[] inputs
    +PortDefinition[] outputs
    +Record_string_any defaultConfig
    +ParamDefinition[] params
  }

  class PortDefinition {
    +string name
    +string type
  }

  class NodeTypeRegistry {
    +Record_string_NodeTypeInfo NODE_TYPE_REGISTRY
  }

  class RsiParams {
    +number period
    +string source
  }

  class ConditionRsiParams {
    +string operator
    +number threshold
  }

  class CrossoverParams {
    +string direction
  }

  class AndOrParams {
    +string operator
  }

  class MarketOrderParams {
    +string side
    +string amount
  }

  NodeTypeInfo "*" o-- "*" ParamDefinition : params
  NodeTypeInfo "*" o-- "*" PortDefinition : inputs_outputs

  NodeTypeRegistry ..> NodeTypeInfo : contains

  RsiParams ..> ParamDefinition : uses
  ConditionRsiParams ..> ParamDefinition : uses
  CrossoverParams ..> ParamDefinition : uses
  AndOrParams ..> ParamDefinition : uses
  MarketOrderParams ..> ParamDefinition : uses

  class RsiParamDefinitionExample {
    +ParamDefinition period
    +ParamDefinition source_options_close_open_high_low
  }

  class ConditionRsiParamDefinitionExample {
    +ParamDefinition operator_options_lt_gt_lte_gte_eq
    +ParamDefinition threshold
  }

  class CrossoverParamDefinitionExample {
    +ParamDefinition direction_options_above_below
  }

  class AndOrParamDefinitionExample {
    +ParamDefinition operator_options_AND_OR
  }

  class MarketOrderParamDefinitionExample {
    +ParamDefinition side_options_buy_sell
    +ParamDefinition amount
  }

  RsiParamDefinitionExample ..|> ParamDefinition
  ConditionRsiParamDefinitionExample ..|> ParamDefinition
  CrossoverParamDefinitionExample ..|> ParamDefinition
  AndOrParamDefinitionExample ..|> ParamDefinition
  MarketOrderParamDefinitionExample ..|> ParamDefinition
Loading

File-Level Changes

Change Details Files
Render select dropdowns for parameters that have predefined options in the flow node inspector UI.
  • Extend ParamInput to accept an optional options list prop.
  • Render a styled element when options are provided, mapping option values to user-friendly labels via PARAM_VALUE_LABELS.Pass options through from required and optional param definitions into ParamInput in NodeInspector.
apps/web/src/components/flows/node-inspector.tsx
Add options metadata to flow param definitions to drive enum-like select UIs for specific nodes.
  • Extend ParamDefinition type to include an optional options array.
  • Populate options for known enum-like params such as indicator source, comparison operators, crossover direction, logical operator, and order side in NODE_TYPE_REGISTRY.
packages/types/src/flow.ts
Normalize backtest symbols (uppercase and slash-stripped) before data loading and Binance API/cache usage.
  • Uppercase the trading symbol at the start of historical data retrieval in DataService.
  • Uppercase and remove slashes from the symbol in BacktestsService before constructing cache keys and performing downstream operations, ensuring BTC/USDT and btcusdt are treated identically.
apps/worker-service/src/backtesting/data.service.ts
apps/worker-service/src/backtests/backtests.service.ts

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Copy Markdown
Contributor

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've left some high level feedback:

  • Symbol normalization is now split between BacktestsService.getCandles (uppercase + slash removal) and DataService.getCandlesFromExchange (uppercase only); consider centralizing this into a shared helper so all callers (including future ones) consistently get the same fully-normalized symbol.
  • The new ParamDefinition.options behavior is wired into the UI but only supports simple string arrays; if you expect more complex option metadata (e.g., value/label pairs or localized labels), it may be worth introducing a typed Option structure now instead of overloading PARAM_VALUE_LABELS.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- Symbol normalization is now split between `BacktestsService.getCandles` (uppercase + slash removal) and `DataService.getCandlesFromExchange` (uppercase only); consider centralizing this into a shared helper so all callers (including future ones) consistently get the same fully-normalized symbol.
- The new `ParamDefinition.options` behavior is wired into the UI but only supports simple string arrays; if you expect more complex option metadata (e.g., value/label pairs or localized labels), it may be worth introducing a typed `Option` structure now instead of overloading `PARAM_VALUE_LABELS`.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

…case

dev added toUpperCase(); fix/#76 extends it with .replace(/\//g, '') for
Binance API symbol format (BTC/USDT → BTCUSDT). Keep fix/#76 version.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
@fray-cloud fray-cloud merged commit 9599144 into dev Apr 2, 2026
3 checks passed
@fray-cloud fray-cloud deleted the fix/#76 branch April 2, 2026 01:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant