지표가 함수가 아닐 때: Rust에서 Quant 연산자 정의
Source: Dev.to
문제의 출처
오늘날 대부분의 기술 지표는 함수로 모델링됩니다: 배열을 받아 값이나 다른 배열을 반환합니다.
하지만 지표가 다음과 같은 경우 이 모델은 무너집니다:
- 지속적인 상태가 필요할 때 (롤링, EMA)
- 시간 순서에 대한 민감도가 필요할 때
- 배치와 스트리밍 모두에서 일관된 의미론이 필요할 때
- 구성 및 스케줄링이 필요할 때
순수 함수 모델은 이러한 제약을 표현할 수 없습니다. Rust에서는 이 제한이 명시적으로 드러납니다:
- 소유권은 상태 책임을 명시적으로 만들도록 강제합니다
- 암시적인 전역 변수는 허용되지 않습니다
- 성능을 위해서는 명확한 실행 경계가 필요합니다
핵심 정의: 연산자 (Operator)
이 문서에서 **연산자(Operator)**는 다음과 같이 정의됩니다:
명시적인 실행 의미론 하에 입력 데이터를 처리하는 스케줄 가능한 실행 단위.
‘함수’라는 용어는 의도적으로 사용되지 않았습니다.
연산자는 다음 조건을 만족해야 합니다:
- 명시적인 입력/출력 의미론을 가져야 함
- 의미론적 실행 단위로 호출되어야 함
- 상태 경계를 명시적으로 소유해야 함
- 구조화되고 관찰 가능한 방식으로 실패해야 함
연산자는 절대로 다음을 해서는 안 됩니다:
- 스케줄링에 대한 결정을 내림
- 시스템 자원을 관리함
- 시스템 수준의 복구를 수행함
의미론적 단위로서의 실행
**실행(Execution)**은 다음과 같이 정의됩니다:
주어진 입력 및 실행 컨텍스트 하에 연산자를 불가분하게 호출하는 것.
핵심 속성:
- 실행은 의미론적이며, 구문적이지 않음
- 연산자는 여러 번 실행될 수 있음
- 실행 간의 관계는 여기서 다루지 않음
실패는 패닉이 아니다
연산자 실패는 **패닉(panic)**이 아닙니다. 이는 외부로 전파될 수 있는 일급 실행 결과이며, 시스템을 중단시킬지는 호출자의 책임입니다.
최소 참고 구현 (v0.1)
다음 코드는 위 정의가 Rust에서 구현 가능함을 증명하기 위해 존재합니다.
pub trait Operator {
type Error;
fn execute(&mut self, input: Input) -> Result;
}
주석:
&mut self은 내부 상태를 명시적으로 허용합니다.- 아직 시간, 배치, 스케줄링 의미론은 포함되지 않았습니다.
- 구현은 의도적으로 최소화되었습니다.
간단한 무상태 예시:
pub struct Sum;
impl Operator for Sum {
type Error = ();
fn execute(&mut self, input: &[f64]) -> Result {
Ok(input.iter().sum())
}
}
이 예시의 목적은 개념을 보여주기 위함이며, 실제 기능을 제공하는 것은 아닙니다.
비목표 (Non‑goals)
이 글은 의도적으로 다음을 정의하지 않습니다:
- 상태 모델
- 시간 의미론
- 배치 일관성
- DataFrame 또는 Polars 통합
엔지니어링 저장소:
연락처: