BLOG main image
ddd (50)
CUDA programming (0)
알고리즘 트레이딩 (5)
Cherry Picker 개발 (23)
TSimulator 개발(종료) (11)
IT 노트 (1)
잡동사니 (2)
사진 (4)
일기 (4)
이력서 (0)
Visitors up to today!
Today hit, Yesterday hit
daisy rss
tistory 티스토리 가입하기!
'트레이드스테이션'에 해당되는 글 10건
2018. 1. 10. 09:44

2014년 4월부터 제도권에서 트레이딩을 한지 5년이 다돼간다. 최근에는 벗어났지만 그 동안 박스권에 갇혀있던 어려운 시장에서도 마이너스 분기실적 없이 잘 견뎌냈다.


현재 사용중인 CherryPicker 는 최초에 개발했던 방향과는 많이 달라졌다(좋은쪽으로). 역시 첫 설계에서 생각했던거와 사용하면서 필요해지는 부분의 차이는 작지 않았다. 아마 이런 툴개발 경험이 없어서인거 같다. 이제는 나뿐만이 아닌 회사 동료분들의 전략 자동화에도 협조하고 있고 그 분들의 요구사항을 반영하면서 기능이 더욱 늘어났다. 특히 수동개입쪽 기능이 많이 추가됐다. 기존의 나는 수동개입은 불허하는 입장이지만 특수한 상황에서는 필요할것 같아 적극 반영을 했다.


사실 트레이딩툴 기본기능은 3년전에 거의 완성됐고 그 이후부터 최근까지는 거의 백테스트에 올인했다고 봐도 좋다. 그 중 분석하기 편하게 GUI 툴 개발과 병렬화에 집중했다. 그래서 테스트 결과를 비쥬얼하게 보여주는 Efreet 가 탄생했고, Efreet 는 결과 분석외에도 테스트 스크립트 기능도 있어서 테스트 설정 및 스케줄이 기록된 스크립트 파일을 읽어서 전략의 백테스트를 진행한다. Efreet 의 백테스트는 복수의 CPU 에 테스트 분량을 분산해서 병렬로 진행하는 기능도 있다. CPU 개수에 따라 테스트에 걸리는 시간이 대폭 줄어든다. 마지막으로 Efreet 의 중요한 기능은 백테스트에서 도출된 경우의수에서 가장 이상적인 경우의수 및 그것들의 조합을 추출하는것이다.. 이 작업 또한 백테스트만큼의 오랜 시간이 소요되는데 역시 CPU 병렬처리를 이용해서 그 시간을 단축시킬 수 있다.


CPU 병렬화는 시뮬레이션의 시간을 단축시켜준다. 위 문단에서 설명한것처럼 CPU개수분의 1의 수준으로 단축된다. 그래도 4코어 CPU 로 많으면 1주일이상의 시간이 소요되는 테스트를 3, 4일로 줄여줄 뿐이다. 물론 이것만으로도 엄청나지만 그래도 목이 마른 법. 며칠이 아닌 1,2 시간 내로 끝내고 싶었다. 언젠가는 계획하고 있지만 당장은 20코어 4프로레서보드 같은 서버를 장만할 수도 없다. 가격도 가격이거니와 최근에 터진 인텔 CPU 보안패치문제 때문에라도 지금은 별 계획이 없다. 그래서 주목하게 된것이 GPU 다.


CPU 보다 훨씬 많은 작은 코어들을 가지고 있는 GPU 의 병렬연산은 알파고의 등장하면서 주목받기 시작했다고 봐도 과언이 아니다. 그래서 나는 약 2년 전부터 이전 증권사에서 연을 맺게 된 분과 CUDA(NVIDIA 에서 개발한 GPU 병렬연산을 쉽게 해주는 언어시스템) 스터디를 시작했다.(현재는 CUDA 스터디를 어느정도 마치고 딥러닝 스터디로 전환) 이 CUDA 가 얼마나 Efreet 의 시뮬레이션 성능을 높혀줄지는 모르겠지만 알파고에서 대량으로 GPU가 운용되는것을 보면 가능성이 있어보인다. 그래서 당분간은 CUDA 프로그래밍에 집중해보려고 한다. 카테고리를 추가해서 관리하고자 한다.


추가로 예전에 올렸다가 지운 CherryPicker 엔진을 사용한 Gaia 의 스냅샷과 Efreet 의 백테스트 결과 분석화면을 올려본다.




Gaia(트레이딩툴) 운용화면






Efreet 백테스트 결과 분석화면(개인적인 부분은 책으로 가림)



2013. 12. 16. 13:36

2011 년 3월..  TradeStation 이 아닌 자기만의 트레이딩툴을 만들고 싶었던 그 때 증권 API 의 존재를 우연히 알게되고, 하루라도 빨리 화면으로 뭔가 표현해보고 싶은 마음에 급조한 프로그램이 있다. 시스템 트레이딩툴은 아니고 종목, 주문 수량,  주문 가격, 주문 타입 등을 선택하고 거래할 수 있는 수동매매툴이다. 지금은 모든 프로젝트가 Cherry Picker 라는 이름으로 통합됐고 더 이상 GUI 는 채용하고 있지 않지만 그 당시에는 TTrader 라는 이름을 지어줬었고, 허접하지만 아래 그림과 같이 GUI 로 정보를 표현할 수 있게 했다. 이 프로그램은 증권 API 테스트를 위해 급조된것에다가 시스템 전략의 수행도 불가능하므로 당연히 현재는 사용하지 않는다. 그래도 묻혀지는 것이 아쉬워 수행되는 모습을 남겨보고자 한다.



( 참고로 현재 운용중인 트레이딩 툴인 Cherry Picker 는 GUI 가 아닌 CUI 방식이며, 로그파일에 현 상황들이 실시간으로 기록이 된다. GUI 가 있으면 화려해보이고 프로그램다운 모습이지만 데이터를 보여주기 위해 필요한 리소스(CPU 등 컴퓨터 자원)가 결코 적지 않으며 무엇보다 시스템 전략은 전적으로 미리 코딩된 로직에 의해서만 운용되어야 함으로 GUI 에 의한 조작이 애초에 필요가 없기 때문이다. 시스템 트레이딩에 특화된 헤지펀드(특히 르네상스 테크놀로지)는 트레이딩룸 자체가 없고 오직 서버실과 전략개발을 위한 회의실, 그리고 개인 사무공간만 존재한다고 어디선가 읽은 기억이 있다. ) -> 이상 GUI 를 안만들어도 된다는 변명 ;;;



사진 2 장과 시연 동영상 1 개를 만들어봤다. 수행 프로그램 이름은 Cherry Picker 로 되어있는데, 이는 어느 시점에서 진행중인 모든 프로젝트 이름을 Cherry Picker 로 통합했기 때문이다. 



서버 접속 직전의 모습 (화면을 클릭하면 크게 볼 수 있습니다.)



첫 번째 사진은 프로그램이 증권사 서버에 접속하기 이전인 프로그램 수행 직후의 모습이다. 왼쪽 검은 화면은 각종 정보메세지를 출력하는 부분이고, 오른쪽 화면이 프로그램을 조작하거나 가격, 계좌정보, 잔고 등을 표현하는 GUI 부분이다.



서버 접속 후의 프로그램 수행중인 모습 (화면을 클릭하면 크게 볼 수 있습니다.)



두 번째 사진은 증권사 서버 접속 직후의 모습이다. 직관적으로 각 버튼 또는 창들이 의미하는바를 쉽게 알 수 있다.



증권사 서버 접속 후 간단한 거래를 하는 모습 (플레이 버튼을 누르면 재생됩니다.)



위 영상은 서버에 접속을 하고 간단한 선물거래를 하는 영상이다. 시계를 보면 9시 직전에 서버에 접속을 했으며 9시00분00초가 되자 수신되기 시작한 실시간 데이터들이 화면에 보여지며, 매수 또는 매도거래가 행해지고 계좌 및 잔고상태를 확인하는 버튼을 누르면 해당 정보가 갱신됨을 알 수 있다. 보다시피 시스템전략과는 무관한 프로그램이며 그냥 편한 수동거래툴(?) 정도로 인식하는것이 좋겠다.


다음 포스팅에서는 본격 시스템 트레이딩툴인 Cherry Picker 의 수행모습을 화면에 담아볼 것이다. (이미 이전 몇몇 포스팅에서 캡쳐사진을 올린바 있지만...) GUI 가 없기 때문에 뭔가 굉장히 단순해 보일지 모르겠지만 그 내부에서는 아주 나이스하게 시스템 전략들이 관리 및 운용되고 있다.

'Cherry Picker 개발 > Cherry Picker 소개' 카테고리의 다른 글

근황  (2) 2018.01.10
Cherry Picker 와 이 블로그에 대한 설명  (0) 2013.09.27
2013. 7. 17. 18:24

직전 일정에서 구현하겠다고 했던 세 가지는 다음과 같다.


1. tick bar 의 생성

2. 직전 봉에서 접수된 주문을 실시간로 체결하는 기능 추가

3. 두 개 이상의 tick bar 또는 tick bar 와 분봉을 한 전략에서 동시에 사용하는 기능 추가


그리고, 위 세 가지를 구현하면 그 다음 구현에 포함되는 세 가지는 다음과 같다.


4. API 에서 받아온 틱데이터를 REAL 모드 전략에 전송

5. tick 멀티심볼을 이용한 간단한 HFT 전략 수행 및 검증

6. 분봉 안에 틱데이터 정보를 넣어 봉가정 없이 정확한 분봉 백테스트가 가능하게 함


지난 3주간 Cherry Picker 에 구현해 놓은 부분을 빨간 색으로 표시했다.

그럼 구현된 부분과 구현되지 않은 부분에 대한 간략한 설명을 하겠다.


==================================================================


1. tick bar 의 생성

구현 자체는 아무런 어려움이 없었다. 시간에 관계없이 지정된 수 만큼의 틱이 쌓이면 봉으로 만들어서 전략에 적용하면 끝이기 때문이다. TS 에서의 틱전략 결과와의 비교는 구조적 결함은 없었기 떄문에 비교적 순조롭게 통과했다.


2. 직전 봉에서 접수된 주문을 실시간로 체결하는 기능 추가

이 기능은 bar assumption 없이 실제로 들어오는 틱에 의해 주문이 체결되는 기능이다. 이 기능을 사용하려면 틱데이터 정보가 있어야한다. OHLC 정보만으로는 bar assumption 만으로만 체결 순서를 짐작해야한다. 실제 거래를 하기위해 반드시 필요한 기능이다. TS 를 실시간으로 돌릴 때는 TS 역시 bar assumption 을 사용하지 않고 이 방법으로 주문을 체결시킨다. (밑에 6번에서 설명하지만 bar assumption... 굉장히 잘 만든 가정같다.)


3. 두 개 이상의 tick bar 또는 tick bar 와 분봉을 한 전략에서 동시에 사용하는 기능 추가

TS 에서 지원하지 않는 기능이다. Cherry Picker 는 기본적으로 이 기능이 가능하게끔 설계되었다. 하지만 기능이 정확하게 동작했는지 검증하기에 많은 시간이 걸리므로 일단은 keep 해뒀다. 이 기능은 Cherry Picker 를 개발하기 시작한 이유중 하나에 해당하는 기능이니만큼 신중을 가하고싶다. 8월부터 구현을 시작할것 같다.


4. API 에서 받아온 틱데이터를 REAL 모드 전략에 전송

이 기능은 지난 주말동안 구현했고 그저께인 월요일부터 회사에서 몰래(?) 테스트중이다. 예전 진행했던 TTrader 프로젝트의 주기능인데 Cherry Picker 로 통합된 이후에 처음 코드를 다시 들여다봤다. 최적화 작업을 조금 해 주고 어렵지 않게 symbol, symbol manager 에 연결할 수 있었다. 전략을 하나만 적용시켜봤는데 사진과 같이 무리없이 데이터가 잘 들어오고, 봉이 잘 생성되고, 전략이 잘 수행되고, 주문도 잘 체결되는걸 보니.. 흐믓.

아무리 데모전략이지만 첫 거래 10분만에 -25 만원... 손절이 잘 되고 있다 :)

약간의 설명은 jisu 로 시작한 줄은 1분이 갱신되고 처음으로 들어온 데이터가 KOSPI200 이라는 말이고 futures 로 시작한 줄은 1분이 갱신되고 처음으로 들어온 데이터가 KOSPI200 선물이라는 말이다. 그냥 디버깅 코드이다. 




5. tick 멀티심볼을 이용한 간단한 HFT 전략 수행 및 검증

지금은 intraday bar 전략을 실시간 테스트중인데, 별 문제가 없으면 7/22 (다음주 월) 부터 테스트에 들어갈 것이다.


6. 분봉 안에 틱데이터 정보를 넣어 봉가정 없이 정확한 분봉 백테스트가 가능하게 함

이 기능은 좋다! TS 에 없는 기능인데, 백테스트시에 틱정보만 있으면 분봉 전략이라고 해도 bar assumption 을 사용하지 않고 틱데이터에 따라 체결처리를 할 수 있다. '분봉전략의 백테스트는 봉가정이 완벽하지 않기 때문에 정확하지 않다.' 는 말에 조금은 반박할 수 있게 됐다. 물론 그 구하기 어려운 틱 정보가 있어야만한다.:)

틱 정보가 있다면 TS 에서도 이 기능을 구현 자체는 가능하다. 틱 전략코드를 잘 수정하고 주무르면 가능하기는 한데 Cherry Picker 에서는 분봉전략 코드를 수정할 필요가 없이 실제 체결순서 여부를 정확히 알 수 있다.

물론 그 시장에 미치는 나의 영향력이 없다는 가정하에서...



이상 블로그 갱신 끝.


P.S.

요즘 빠져있는 '이매뉴얼 더만' 이 쓴 '퀀트(영어제목은 My life as a quant)' 라는 책.. 좋다.

이 분야에 관심이 없는 사람은 재미가 없겠지만 퀀트들이 주로 어떤 일을 하는지 저명한 퀀트의 눈으로 간접경험이 가능하다.

'Cherry Picker 개발 > 일정(종료)' 카테고리의 다른 글

13년 12월 ~ 14년 1월 일정  (0) 2013.12.11
10~11 월 일정 (2013년)  (0) 2013.11.21
SetTimer 함수를 도입  (0) 2013.11.08
의미있는 일정  (0) 2013.06.17
새 통합 프로젝트 "Cherry Picker" 킥오프  (0) 2012.12.22
2013. 5. 30. 10:47

이번에는 멀티심볼에서 특정 함수 수행시 주의할 또다른 점에 대해 정리해 보겠다.


TS 내장함수 중(read only 함수) 다음과 같은 구현이 있는 함수가 있다.



형태 '가'

=================================

if( CurrentBar = 1 ) then

begin

....

end;

else

begin

...

end;

=================================


함수가 이런 형태를 가졌다면 보통 매 봉마다 무조건 수행이 되야하는 함수이다. ( TS 에서는 이러한 함수를 series function 이라 부른다. )

내장함수의 이런 방식은 TS 8.7 버전에서 보이고 옛 버전인 2000i 버전에서는,



형태 '나'

=================================

if( CurrentBar >= 1 ) then

begin

...

end;

=================================


같은 형태이며, 이 방식이 좀 더 맞는 방식이라고 생각하는데, 그 이유는 CurrentBar 가 0 일 때 아무것도 수행하지 않으므로 0 을 리턴할 수 있기 때문이다. 하지만 8.7 버전의 형태(형태 '가')는 CurrentBar 가 0 인 경우 else 부분이 수행되는 로직이다. 이 경우 리턴되는 함수의 값이 대부분 0 이 아닐 것이고 이 내장함수의 의도는 CurrentBar 가 2 이상일 때 else 부분이 수행되는것이므로 첫 번째 전략을 돌 때는 이와 같은 형태의 함수의 사용은 주의를 요한다.


TS 에서 어떤 생각을 가지고 이런 구현을 했는지 궁금할 따름...


여기서 더욱 재밌는 점이 있다. 1분 심볼과 5분 심볼을 사용하는 전략을 예로 들겠다. 

이 결과는 TS 8.7 버전의 경우이므로 그 이전버전은, 즉 형태 '나' 방식의 내장함수를 사용하는 TS 는 다른 결과가 나올 수 있다.


================================

전략의 첫 번째 루프:

첫 번째 심볼의 CurrentBar 는 1.

두 번째 심볼의 CurrentBar 는 0.

================================


여기서 두 번째 심볼을 사용하는 형태 '가' 의 내장함수(RSI 라 가정하자)는 0 이 아닌 값을 리턴할 것이다.

예를 들어 0 이 아닌 0.5 을 리턴한다고 가정하자. 그럼 다음 과 같은 결과가 나온다.


Value1 = RSI Data2;


Value1 은 0.5 이다.


그럼 다음 전략 루프를 보자.


================================

전략의 두 번째 루프:

첫 번째 심볼의 CurrentBar 는 2.

두 번째 심볼의 CurrentBar 는 0.

================================


아직 두 번째 심볼의 CurrentBar 는 0 으로 아직 새로운 봉이 생성되지 않았다. 그러므로 첫 번째 루프에서 구한 값과 같은 값을 리턴해야하는것이 정상이다. 하지만 실제 리턴되는 값은 다음과 같다.


Value1 = RSI Data2;


Value1 은 0 이다.


첫 번째 루프에서의 0.5 는 어디로 간 것일까... 참고로 이후 두 번째 심볼의 CurrentBar 가 1 이 되기 전까지 'RSI Data2' 의 값은 계속 0 을 리턴한다. 즉, 내부 결과값들이 모두 초기화 됐다는 말이다. 필자가 TS 를 벤치마킹한 프로그램을 구현하면서 내린 결론은 다음과 같다.


1. 전략 코드에 if 문이 쓰이고 위와 같은 RSI 함수가 if 문 내부에서 쓰였다고 가정하자.

2. 전략이 if 문 내부로 분기되지 않는다고 해도 RSI 함수 내부는 수행되어야한다.

3. C++ 상에서 이것이 가능하게 만들기 위해서는 (물론 더 좋은 방법이 있겠지만 필자가 구현한 대로라면) 이런 형태의 함수는 각각 ID 를 가지게 하고 ( 예를들어 RSI( Close, 10 ) 과 RSI( Close, Value1 ) 은 Value1 의 값이 10 이라고 해도 다른 ID 를 가지게 한다.) 함수 내에 사용되는 심볼이 갱신이 될 때마다 전략 루프 돌기 전에 수행을 시켜줘서 미리 값을 구해놓아야한다. 여기서 모든 함수들의 ID 를 구하는 작업이 필요한데, CurrentBar 가 0 이던 아니던 무조건 첫 한 번은 수행을 시켜서 ID 를 구하는 로직을 TS 에서는 사용하지 않았을까 싶다. 그래서 결국 수행되지 말아야할 CurrentBar 가 0 인 상황에서도 함수가 수행되었고, ID 를 구한 상태에서는 내부적으로 가지고 있는 결과값 배열을 전부 0 으로 초기화를 시킨것이 아닐까... 라는 소설을 써본다. 사실 필자는 이런 TS 의 결과를 보고 위와 같은 방식으로 코딩을 해놓았다.


결론적으로 위와 같은 오류를 피하기 위해서는 다음 두 방법을 사용하자.


1. 형태 '가' 와 같이 된 내장함수를 사용하지 말고 모두 형태 '나' 와 같은 커스텀함수를 만들어서 사용한다. (내장함수가 형태 '나' 라면 그냥 둬도 된다.)

2. 전략 자체를 사용된 심볼의 current bar 가 1 이상일 경우에만 수행되게 만든다.


첫 번째 봉이 나오자마자 주문이 나갈 일은 거의 없겠지만 시스템 버그를 미연에 방지하기 위해서는 어쩔 수 없는듯하다..

2013. 5. 25. 08:41

멀티심볼 데이터를 TS 함수에서 사용할 때 주의할 점이 있다. build-in 함수를 포함하여 user-defined 함수를 만들때도 반드시 참고해야하는 사항이다. 결론부터 말하면


1. 함수 인자에 두 번째 심볼 데이터(ex. close data2)를 직접 넣으면 함수 내부적으로 사용되는 심볼 데이터는 모두 두 번째 심볼 데이터를 사용한다.

2. 함수 인자에는 두 번째 심볼 데이터, 함수 내부에서는 첫 번째 심볼 데이터가 사용되길 바란다면 두 가지 해결방법이 있다. 

    a. 별도 변수에 두 번째 심볼데이터를 대입한 후 그 변수를 함수 인자로 사용한다.

    b. 인자로 바로 두 번쨰 심볼데이터를 사용하고 function( ... ) data1 과 같이 사용한다.



이제 위에 언급한 내용들을 좀 더 자세히 설명하겠다.

예를 들어 다음 과 같은 인터페이스를 가진 함수가 존재한다고 하자.


testFunction( NumericSimple aNum );


그리고 이 함수 내부에서는 다음과 같이 심볼 데이터인 close 를 사용한다고 가정하자.


input: aNum


testFunction = close * aNum;


인자로 넘어온 aNum 이라는 변수에 종가를 곱하여 리턴해주는 단순한 함수이다. 그럼 다음과 같은 사용을 해보면 어떤 결과가 나올까? ( close 는 200, close data2 는 300 이라 가정)


Value1 = testFunction( 10 ); 


Value1 에 리턴된 값은 함수 내부계산이 10 * 200 이므로 2000 이 될것이다.


Value1 = testFunction( close );


이번엔 close * close 가 계산되어 40000 이 리턴될 것이다. 그렇다면 다음은 어떨까?


Value1 = testFunction( close data2 );


직관적으로는 300 * 200 으로 60000 이 되야하지만 실제 계산은 300 * 300 이 되어 90000 이 리턴된다.

이를 의도한대로 계산되어지게 하려면 다음과 같은 방법을 사용해야한다.


== 첫 번째 방법 ==

Value99 = close data2;

Vallue1 = testFunction( Value99 );


== 두 번째 방법 ==

Value1 = testFunction( close data2 ) data1; 


첫 번째 방법에서 사용된 Value99 는 심볼 데이터가 아니므로 함수 내부에서 사용되는 심볼 데이터는 default 인 첫 번째 심볼을 사용한다. 

두 번째 방법에서 함수 뒤에 사용된 심볼 데이터 번호(여기서는 data1)는 은 원래 함수에 사용된 인자들이 심볼 데이터인 경우, 인자들을 모두 해당 심볼 데이터 번호로 바꾸고 함수 내부에 사용된 심볼들도 마찬가지로 해당 심볼 데이터 번호로 바꾸는 기능을 한다. 하지만 이렇게 심볼 데이터 번호가 바뀌는 대상은 default 심볼 데이터를 사용한 경우이고 특정 심볼 데이터 번호가 붙어있는 심볼 데이터(ex close data2) 는 다른 심볼 데이터로 변경되지 않는다. 그러므로 두 번째 방법의 경우 인자는 다른 심볼로 변환되지 않고, 함수 내부 심볼만 변경되어 의도한 값을 얻어낼 수 있는것이다.

2013. 5. 19. 08:19

거의 반년만의 포스팅같다.


먼저 간략하게 추가된 사항을 나열하겠다.


==============================================

추가된 사항

==============================================


1. 주문입력값이 호가와 일치하지 않는 경우, (예를 들어 KOSPI200 선물은 200.22 일 때) 내부적으로 가격 조정을 하는데 이 알고리즘을 테스트 후 적용했다.


2. 멀티심볼을 적용하는데 있어 생기는 문제점들을 해결했다. 각 심볼들이 MaxBarsBack 을 채우고나서 CurrentBar 및 BarNumber 가 1로 시작을 하게되는데, 기존 가정이 틀린 부분이 있어 수정 및 테스트 완료했다.

그리고 TS 8.7 버전에서 BarNumber 증가에 관한 버그를 발견한것 같은데, 멀티심볼의 경우 두 번째 이후의 심볼은 경우에 따라 CurrentBar 와 BarNumber[0] 가 일치하지 않는다. 이런 버그까지 CherryPicker 에서 재현되도록 적용할 필요는 없을것 같다.


3. 멀티심볼을 구성하는 경우 다음 두 규칙을 따르게 했다.


(1) 거래 대상 심볼은 가장 작은 time interval 을 가지고 있어야한다.

    : 내부적으로 최소 time interval 을 가진 봉이 완성되면 주문 및 체결이 이루어지는 구조다.

(2) 큰 time interval 의 심볼의 time interval 은 작은 time interval 의 심볼의 time interval 의 배수가 되는걸 추천.

    : time interval 이 1 과 3 인 전략은 3이 1의 배수이므로 3분 봉이 완성될 때 언제나 1분봉도 같이 완성되어

      (1) 규칙을 언제나 만족시킨다. 하지만 time interval 이 3 과 5 의 심볼을 가진 전략은 5, 10, 15, 20 분에도 

      전략은 루프를 돌지만 5, 10, 20 분에는 주문 및 체결조건을 만족해도 주문 및 체결이 이루어지지 않는다.


* 위 추가된 사항 '3' 에서 설명한 '루프를 돌지만 주문 및 체결이 되지않는 상황' 에서의 로직은 단순하다. 최소 time interval 심볼이 봉을 완성되지 않은 상태에서 다른 time interval 을 가진 심볼이 봉을 완성하면 해당 상황을 만족시키게 되는데, 이 때 발생하는 주문은 그냥 무시하고, 이전에 주문한 조건이 수행되지 않게끔 한다. 그리고 해당 루프를 돌 때 전략 변수들을 조작할 수도 있는데 값 변경은 실제로 이루어지게 설계하되, 다음에 최소 time interval 을 가진 심볼이 봉을 완성하면 변경된 값을 undo 처리하여 복원한다.


4. session 이 끝나는 시간을 심볼의 time interval 크기에 따라 조절할 필요가 있다. 1, 3, 6, 30 분 심볼을 예로 들어보자. 선물 동시호가가 시작되면,


* 1 분 심볼의 경우 15:00, 15:01, 15:02, 15:03, 15:04, 15:05, 15:15 에 봉이 완성

* 3 분 심볼의 경우 15:00, 15:03, 15:06, 15:15 에 봉이 완성

* 6 분 심볼의 경우 15:00, 15:06, 15:18 에 봉이 완성

* 30 분 심볼의 경우 15:00, 15:30 에 봉이 완성


위와 같이 봉이 완성이 되는데, TS 에서 session end time 을 15:20 으로 설정을 하면 1, 3, 6 분 심볼의 경우 영향이 없지만 30분 심볼의 경우 마지막 봉이 15:30 이 아니는 15:20 으로 되어 정확한 봉 완성 시각이 설정되지 않는다. 그러므로 큰 time interval 을 사용할 경우 session end time 을 그에 따라 적절하게 늘릴 필요가 있다.




이상이다. 10 년 이상의 데이터를 이용하여 TS 에서 print로 찍어낸 로그와 일치시키는데 지금까지 가장 많은 시간이 걸렸다. 멀티심볼 적용도 테스트가 끝난 현 상황에서 필자에게 할당된 시간의 100% 를 내부로직 기능 추가에 할애하기보다 '돈'을 벌 수 있는 로직을 공부하는 시간을 절반가량 할애할 생각이다. 추가해야할 함수도 많기에 앞으로의 포스팅은 추가된 함수 및 전략을 중심으로 진행하되 간간히 내부로직 기능 추가를 포스팅할 생각이다.

2012. 9. 10. 13:36

TS 의 기능은 많다 그것도 아주 많이.. 그 많은 기능들을 하나하나 개인이 벤치마킹하기에는 좀 부담스러운건 사실이다. 하지만 대부분 일반적인 시스템 거래에서는 쓰이지 않으며 또 쓰인다 한들 현재 진행중인 프로젝트의 기능 테스트만 제대로 구축한 상태라면 1. 기능 추가, 2. 전체 기능 테스트 수행 <-- 이거면 끝이다.


현재 프로젝트를 진행하면서 굵직굵직한 기능들을 추가하면서 완전한 TS 또는 그 이상의 기능에 도전해왔다.

지금까지의 TSimulator 는 멀티 심볼 기능을 지원했지만, 1분봉만 사용할 수 있는 제한적 기능이었다.

하지만 이 기능만으로 TS 의 주문 알고리즘과 함수 알고리즘을 테스트 하기에는 무리가 없었다.


하지만 주문 알고리즘, 함수 알고리즘은 끝낸 시점에서 남은 작업은 복수의 time frame 을 심볼에 등록할 수 있게 만드는 일이다. 이 작업이 끝나면 남은 굵직한 작업은 다음과 같다.


1. 전략의 결과 분석 툴

2. 실시간 데이터와의 접목


1번의 전략의 결과 분석 툴은 시간문제일 뿐 어려운 작업은 없다. 여기서 중요한건 TS 에서 제공하는 결과 분석 툴 이상의, 다양한 툴을 앞으로 개발해 나가는 것이다.

2번의 실시간 데이터와의 접목... 이거 역시 시간문제인데, 하나의 문제점이 있다면 TS 에서의 실시간 거래 결과와 또 비교를 해봐야 하는데, 과거 데이터야 이미 어마어마한 테스트 자료가 있지만 실시간 처리가 잘 되는지는 매일매일 신경을 써줘야하는 부분이다. 하지만.. 이것도 밀어붙이면 다 해결될 일... 


각설하고.. 결과적으로는 멀티 심볼 적용 작업이 완료되었다. 이제부터 당분간은 테스트 케이스를 늘려나가는 작업에 들어갈 것 같다. 이 작업이 참 재미있는게, TSimulator 결과 TS 의 그것과 일치하면 일치하는대로 좋지만 뭔가 허전하다. 회사 팀장님이 새로 개발중인 프로그램에서 버그가 많이 나오면 호신호라고 말씀하신게 심히 공감이 간다. 너무 일이 잘 진행이 되면 불안한 기분이랄까.. 무튼 그렇게 완성도를 높혀가는게 정석이라고 여겨진다.


이전에 포스팅 한 글 중에 CEP 엔진을 이용한 시스템 트레이딩 개발을 시작하려고 한다는 글이 있을것이다. 그런데 TSilmulator 에서 작은 버그들이 계속 터지면서 그동안 나름 바빴서 아직 시작을 못했다..^^;; 당분간 테스트 케이스를 늘려가면서 천천히 시작해야할것 같다.. 시기는.. .9월 말쯤부터...?

2012. 8. 24. 16:00

개발환경, 그리고 현재 진행중인 프로젝트의 벤치마킹 제품은 Tradestation 의 버전을 업그레이드 했다.

업그레이드 내용은 다음과 같다.


Tradestation 2000i -> Tradestation 8.7

Visual Studio 6.0 -> Visual Studio 2008


두 제품 모두 한 단계가 아닌 여러 단계 버전 업그레이드다. 업그레이드 이유는 다음과 같다.


* 현재 쓰고 있는 개발장비는 37만원짜리 넷북이다. Visual Studio(VS) 6.0 을 처음에 채용한 이유는 몇 가지 있는데, 가장 큰 이유가. 이트레이드 API 를 사용한 개발은 ViS 6.0 으로만 가능하다고 한 API 개발자의 발언 때문이다. (하지만 실제로는 6.0 이상 버전에서도 아무 문제 없이 작동한다.) 두 번째 이유로는 개발장비의 성능이다. 넷북은 느리다. 하지만 VS 6.0 은 무리없이 원만한 속도로 잘 돌아간다.

  하지만 VS 6.0 에서 발견되는 여러 버그와, 개발의 편의성 등을 따졌을 때 상위 버전의 IDE 가 필요했다. 그래서 업그레이드를 강행하였는데, 6.0 에 비해 많이... 좀 많이 느려지긴 했지만.. 개발 편의성은.. 많이 괜찮아 진듯 하다. 대.만.족.


* Tradestation 의 업그레이드 이유는 분명하다. 바로 기본적으로 사용되는 변수 타입...!! 기본적으로 float 타입의 변수를 사용하여 계산되는 2000i 와 달리 TS 7.0 이상의 버전에서는 double 을 사용한다. 비록 데이터 크기는 두 배 (4 byte -> 8 byte ) 증가하지만 계산 결과의 정확도는 비교할 수 없을 정도로 증가한다. 사실 처음에 TS 2000i 가 float 타입을 쓴다는걸 알았을 때 적잖히 당황했다. 도대체 왜... 부정확한 연산을 하려하는지.. 추측건데 2000i 가 나왔을 당시 개인용 컴퓨터에 주로 쓰이는 메모리 용량이 작아서 그런게 아닐까 싶다. 

  TS 8.7 로 업그레이드를 성공하고 나서 3rd party 데이터를 불러오는데 애좀 먹었지만 지금은 잘 작동되고, TS2000i 에서 일치하지 않던 결과들도 모두 정확하게 일치함에 감동의 눈물이... 

  TS 업그레이드의 이유를 하나 더 들자면 '두 변수의 비교' 방식이다. TS 2000i 나 8.7 에서 두 변수 A, B 를 비교할 때 A 에서 B 를 뺀 후, 절대값을 취한다음 그 오차가 기준값 이하면 두 값이 같다고 판단을 하는데, 그 기준값의 크기가 2000i 의 경우 커서 정밀도 있는 계산을 할 때에는 서로 다른 값임에도 불구하고 같다고 해버린다. (대략 기준값이 5.0e-6 란다) 하지만 8.7 에서는 그 기준값이 기본값으로 2.2204460492503131e-012 로 아주 정밀하게 설정되어 있다. 이렇게 할 수 있는 이유는 정밀도 높은 double 타입을 사용하고 있기 때문이다. 


이상 두 프로그램의 업그레이드 이유에 대해 적어봤다;; 

2012. 7. 16. 10:57

그간 회사에서 일하다가 몇 번 개발 진도 보고를 시도해 보았는데 팀장님 눈치에 번번히 실패했다.

오늘은 팀장님이 오전반차라 조금 여유를 가지고 개발 진도 보고를 써보겠다.


직전 3월에 쓴 개발일정은 뒤로 하고 현재 생각나는 수정사항을 적어보면,


1. 데이터 타입을 새롭게 리뉴얼 했다. 데이터 타입 종류는 

    NumericSimple (input용)

    NumericSeries (variable용)

    NumericFunction (함수용)

와 같이 구성하였다. 전략 코드에서는 float 나 int 타입의 데이터 대신에 모두 NumericSimple 이나, NumericSeries 를 써야한다. 이렇게 구성하면 비용은 아~주 조금 더 들지 모르겠지만 함수 클래스 구현이나 전략 코드 상에서 계산 수행 시, 복잡하지 않고 좋다.


2. 간편한 함수 클래스 추가 :

모든 데이터를 NumericSimple, NumericSeries 로 관리하다보니 함수 추가가 아주 쉬워졌다. 프레임을 한 번 만들고 나니 왠만한 TS 에서 구현된 함수는 뚝딱 만들어 낸다. 그래서 굳이 시간날 때마다 함수 클래스를 열심히 만들 필요 없이, 필요할 때마다 만들어 내면 되겠다.


3. 전략 결과의 정확성 증대 :

처음에는 전략을 추가할 때마다 두려웠따. 왜냐? 트레이드스테이션의 결과와 불일치 하는일이 비일비재 했기 떄문이다. 그렇게 버그를 점점 수정해 나가고 현재 17개의 전략의 결과가 같아지기까지 꽤 정확도가 높아졌다. 억지로 말도안되는 주문들을 내봐도 결과가 같아지는 걸 보면 참 뿌듯하다.

얼마전에 일어난 하나의 에피소드를 얘기 해보겠다. 결과값이 -530 만원이 나와야 하는데 -590 만원으로 나왔다. TS 에서 찍어본 주문 가격들은 다 일치했다. 이렇게 되면 내부 주문 알고리즘이 잘봇 코딩되었다는 얘기가 되므로 안을 들여다봤다. 대략 3개월 만인가...? 너무 오랜만에 보는 코드들이라 한참을 들여다 보는 일이 생겨버렸다. 내가 짠 코드임에도 불구하고....  이건 능숙한 개발자들, 아니 인간이라면 누구나 쉽게 경험하는 일이다. 그래서 주석의 중요성은 몇 번 강조해도 지나치지 않은가 보다. 다행히 나의 한계를 인정하고 열심히 주석처리를 해온 덕분에 디버깅은 그리 오래 걸리지 않았다. 원인은 long 처리 코드와 short 처리 코드 작성시 copy & paste 를 하는 도중에 미처 수정하지 못한 탓이었지만;; 

결론은 현재 왠만한 전략은 같은 결과를 내어줘 신뢰성이 꽤 높은 상태에 다다랐다는 점.


4. 복수 심볼 사용 가능 :

이건 이틀 전에 추가한 기능이다. Close, CloseOfData2, CloseOfData3 와 같이 심볼을 추가하면 다른 심볼도 전략에서 참고할 수 있게 되었다. 프로그램 수행 시, 데이터만 로딩되어 있다면 매크로 한 줄로 전략에 심볼을 추가하는게 가능하다. 아직 완성되지 못한게 두 가지 있다면, 함수 자체에 다른 심볼 적용 (Average( Close, 3) of Data2 와 같이 ) 의 인터페이스를 아직 못정했고, PercentR( 30 ) of Data2 로 사용 할 경우 함수 내부에서 두 번째 심볼에 대한 정보에 접근해야 하는데, 이 알고리즘도 아직 결정을 못하였다. 이것들을 결정하려면 몇 가지 정보가 수집되어야 한다. 앞으로 구현할 전략들 중에 심볼을 가장 많이 추가할 전략은 몇 개의 심볼을 사용하는지.. 많이 사용한다면 심볼 번호를 인자로 받을 것이고 기껏해야 2,3개의 심볼이라면 일일히 AverageOfData2 와 같이 함수를 늘려갈 것이기 떄문이다. 





앞으로 추가될 기능들 (될 수 있으면 7월 안에)


1. 위 4 번의 심볼 작업 마무리

2. 타임프레임 조절 기능

3. 주문 제한 기능 (현재는 피라미드식 주문으로 주문에 제한이 전혀 없음. 예를 들어 현재 long 포지션이면 long 주문 불가)

4. 프로그램 구동 시, 데이터 파일 이름, 데이터 파일 위치 등 데이터 관련된 클래스를 만들어 관리 가능하도록


이상이다. 

2012. 3. 16. 10:58
TS 의 함수의 많은 부분이 기술적 분석 치표를 그리는데 필요한 값을 구하는 함수이다. (ADX, RSI, DMI 등)
이 함수들을 포함한 많은 TS 의 기본함수들은 일반적인 프로그램에서 구현하는 함수와는 조금 다른 특성을 가지고 있다.

"historical value"

무슨 말이냐 하면 예를 들어 설명하자. aaa() 라는 함수가 있다. 이 함수의 구현은 다음과 같다. 

////////////////////////////////////////////////////////////////////////////
Vars: a(0), b(0);

a = 0;
b = 0;

if (CurrentBar = 1) then begin
    b = 10;
    aaa = b;
end
else
    // a 에 필요에 의한 임의의 값을 대입
    b = a + b[1]; // 'b[1]' 은 이 함수의 1기 전의 b 의 값, 그러니까 현재 9시 10분이면 9시 9분에 돌린 b 의 값
    aaa = b;
end;
////////////////////////////////////////////////////////////////////////////

대충 이렇다. 변수 a 는 전혀 중요하지 않으니 변수 b 에만 주목하자. 이 함수가 정상적으로 동작하기 위해서는 TS 에서는 1기 전의 b 의 값, 그러니까 b[1] 의 값을 어디엔가 가지고 있어야한다.  초보자들은 저 코드를 보면 도대체 어디에 그 값을 가지고 있지? 라고 생각이 든다. TS 에서 사용하는 EasyLanguage 는 너무 고수준 언어라서 그런 잡다한건(중요하지만) 다 내부적으로 처리할것이다. 그래서 필자는 c++ 로 TS 함수를 구현할 때, 함수 내부에서 static map 을 사용하여 관리한다.

이거 말고도 TS 코드에 나타나 있지 않은 비밀들이 많다. 가장 큰 비밀은 바로 저런 과거값을 사용하는 함수들은 전략 코드에서 실제 사용이 되던 되지 않던 무조건 수행된다는 점.. 이건 다음에 기회가 되면 적어보도록 하겠다..  필자같은 초보 코더들은 이런 로직을 알아내는게 꽤 큰 난관이다. TS 함수 로직을 열심히 print 찍어가면서 알아내면서 큰 난관을 5개 정도 만났는데 지금은 어느정도 안정화가 된거 같아 전략 개발에만 신경쓸 수 있는날이 머지 않은거 같다.. 끝! 
prev"" #1 next