[1] rust crypto_trading_server

wangki·2026년 2월 25일

trading_project

목록 보기
2/6
post-thumbnail

디버깅 노가다 진행 중...


폴더 구조 변경

기존에 crypto_trading_server 프로젝트에 backtest, db, algorithm, binance 등 여러 모듈을 가지고 처리했다. 백테스트를 하려고 바이너리 크레이트를 만드려고 하는데 라이브러리 형태가 아니라서 가져다 쓰기가 불편했고 examples로 만들자니 마음에 들지 않았다. 나중에 재활용할 수 있는 모듈들을 분리하기로 했다. 폴더 구조는 아래와 같다.

 trading_project/
  ├── crates/
  │   ├── trading_core/          # 핵심 거래 로직
  │   │   └── src/
  │   │       ├── algorithm/     # 거래 알고리즘
  │   │       │   ├── ema_inflection.rs
  │   │       │   ├── ema_disparity.rs
  │   │       │   ├── stop_hunting.rs
  │   │       │   └── mod.rs
  │   │       ├── backtest/      # 백테스팅
  │   │       │   ├── types.rs
  │   │       │   └── ...
  │   │       ├── binance/       # 바이낸스 API
  │   │       │   ├── client.rs
  │   │       │   ├── types.rs
  │   │       │   └── mod.rs
  │   │       ├── indicator.rs
  │   │       └── klines.rs
  │   │
  │   ├── trading_server/        # 서버 애플리케이션
  │   │   ├── src/
  │   │   │   └── worker/
  │   │   └── .claude/           # 문서 및 계획
  │   │
  │   └── backtest/              # 백테스트 관련
  │
  └── Cargo.toml                 # 프로젝트 설정

root 폴더를 잡고 workspace의 member로 각각 크레이트들을 추가하였다.
trading_core를 메인 라이브러리로 잡고 backtesttrading_server에서 사용하도록 했다.


백테스트

backtest 바이너리 크레이트를 만들었다. 소스는 아래와 같다.

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    tracing_subscriber::fmt()
        .with_line_number(true)
        .with_file(true)
        .init();

    let mut engine = ready_for_backtest().await?;
    
    Ok(())
}

async fn ready_for_backtest() -> anyhow::Result<()> {
    let ema_double_filter_strategy = EmaDoubleFilterStrategy::new(500);

    // db init 
    let connection_string = "postgresql://postgres:2677@192.168.1.114:5432/postgres";       // linux
    let db_client = DbClient::new(connection_string).await?;

    let res = trading_core::backtest::run_backtest(&db_client, "BTCUSDT", Box::new(ema_double_filter_strategy), 60*24*180, 100.0).await?;
    trading_core::backtest::print_report(&res);

    Ok(())
}

run_backtest함수에 사용할 알고리즘 전략을 Box<dyn StrategyExecutor> 형태로 매개변수로 넣을 수 있도록 설계하였다.

pub trait StrategyExecutor: Send + Sync {
    fn process(&mut self, candle: &Candle) -> Option<Signal>;
    fn get_state(&self) -> String;
    fn reset(&mut self);
}

백테스트에 쓰일 전략은 StrategyExecutor을 구현하도록 했다. 각 전략은 다르지만 Signal을 받아서 매수, 매도, 손절 등 실제 거래처럼 처리하기 위함이다.


결론

백테스팅을 돌렸는데 거래내역이 하나도 없어서 당황스러웠다. 위 사진처럼 실제 차트와 로그를 비교하며 어느 부분을 개선해야 할지 찾아야 할 것 같다. 이제부터 시작인 것 같다.

0개의 댓글