dated 클래스에 approximate_date()함수추가

dated 클래스를 가지고 놀다보니 백테스팅을 할 때 필요한 것이 하나 생각 났습니다. 가령 t0시점에서 3개월후 주가를 쓰려면 add_months()함수를 이용하여 구하면 됩니다. 그러나 그 날짜가 토/일/공휴일이라면 분명 주가는 없겠죠. 따라서 존재하는 비슷한 날짜의 것을 가져다 써야 합니다. 그래서 근사값을 구하 듯 해당날짜와 가까운 날짜(여기선 이후 날짜로만 검색)를 검색하여 주가를 가져올 필요가 있습니다.

그래서 주어진 날짜와 가장 가까운 날짜를 돌려주는 approximate_date()를 10% 국산기술로 만들어 dated클래스의 멤버함수로 추가하였습니다.
template <class T> date dated<T>::approximate_date(const date& indate) const{
date d=indate;
if (!d.valid()) return date();
if (d<=first_date()) return first_date();
if (d>=last_date()) return last_date();
while(!binary_search(dates_.begin(),dates_.end(),d)){
if(d++>=last_date()) return last_date();
}
return d;
}
이제 제대로 작동하는 지 확인해볼까요?
cout<<"approximate date of '2001-12-08'? "<<dd.approximate_date(date(20011208))<<endl;
2001년 12월 8일은 토요일이라 월요인인 12월 10일에 데이터가 있습니다. 따라서 위의 함수는 '20011210'을 돌려 줍니다. 이번엔 각각에 대해 3개월이후 날짜를 구하고 혹시 그 날짜가 없다면 다시 거기서 가까운 날짜를 구하는 것을 해볼까요?
int main()
{
char* filename="skt.txt";
long yymmdd,price;
dated<long> dd;

ifstream inf(filename);

if(inf.fail())
{
cout<<"Cannot open input file."<<endl;
return 1;
}

while(inf>>yymmdd>>price)
dd.insert(date(yymmdd),price);

for(int i=0;i<dd.size();i++){
date d=dd.approximate_date(add_months(dd.date_at(i),3));
if (d>=dd.last_date()) break;
cout<<dd.date_at(i)<<": "<<dd.element_at(i)
<<"\t"<<d<<": "<<dd.element_at(d)<< endl;
}
inf.close();
return 0;
}

1-2 컬럼이 raw데이터의 내용이고, 3-4 컬럼이 3개월후의 날짜와 종가입니다.

by 타임버드 | 2012/01/31 13:08 | C/C++/C# | 트랙백 | 덧글(0)

Bernt Odegaard's date and dated class


연초마다 반복되는 새해 결심중 하나는 '올해 꼭 딴 것에 눈 돌리지 말고 c/c++이나 해서 vba수준으로 끌어 올리기'이다. 그래서 2012년에도 쌓아둔 책을 다시 읽고 공부를 하는 중인데, 주 목적은 '면접용'이다(그렇다고 면접 보자는 외국회사는 아직 없다-걔네들이 사람볼줄 아나봐)

프로그래밍 언어를 익히는 가장 좋은 방법은 별다른 게 없다. 그저 코드를 연신 찍어 대는 손가락이 필요하고, '소설은 엉덩이로 쓰는 거'라는 어느 소설가의 말처럼 진득히 자리에 앉아 있어야 한다. 눈으로 백날 좋은 책 읽고 책의 예제나 따라해 봐야 '햄스터 통굴리기'이다.

Bernt Odegaard교수의 홈페이지에는 'financial numerical recipes' 외에 그가 각종 연구에 사용하기 위해 만든 'c++ classes for empirical financial data'가 있다. 'financial numerical recipes'도 좋은 학습자료이지만 'c++ classes for empirical financial data' 역시 꽤 잘 만든 학습자료이다. 초보자가 이해하기 쉬운 수준이지만 심플하고 우아한 느낌이 든다. 아무래도 선생님이시다보니 잘 하시는 듯
    'c++ classes for empirical financial data'에는 다섯 가지 클래스가 있다.
  • date 클래스-뒤에 나오는 네 가지 클래스의 베이스인데, 날짜를 다룬다. 
  • dated 클래스-시계열 데이터를 다루기 위한 것으로 date클래스를 템플릿화하여 만든 것이다.
  • dated observations 클래스-dated클래스를 elements를 double로 하여 일반적인 시계열 데이터를 다루는 클래스
  • security price history 클래스-dated observations 클래스와 거의 같으며 bid/ask/trade 데이터를 다룬다.
  • stock price history 클래스-위의 클래스에서 주식에 특화하여 배당금 처리,가격조정이 가능한 클래스

위에서 dated 클래스나 dated observations 클래스 정도만 써도 충분할 듯하다. 그런데 이 소스를 다운로드 하여 사용하려니 소스코드에서 몇 가지 빠지거나 이를 설명한 pdf파일의 내용과 다른 것이 있다(아무래도 잠시 관리를 소홀히 하신듯)

가령 (1) doc_date.pdf에서 date클래스 생성시 date d(19930624); 를 소개하고 있는데, 실제 소스코드에서는 그런 date클래스 생성자가 없다. 예전에 있었던 걸로 아는데, 최근 소스코드에는 디폴트 생성자와 date(const int& d, const int& m, const int& y); 만 있다.

(2) 또 다음과 같은 연산자 오버로딩이 빠져 있다.
date operator +=(date&,const int&);
date operator -=(date&,const int&);
date operator +(const date&,const int&);
date operator -(const date&,const int&);

(3) 클래스의 멤버함수도 아니고 그리 중요한 것은 아니지만 다음과 같은 함수가 예전소스와 달리 빠져 있다(중요하지 않은 것 같아 빼버리신듯)
date next_month(const date& d);
date add_months(const date& d,const int& no_months);

(4) 또 dated_search.h에서 binary_search()함수를 사용하면서 #include <algorithm>를 빼먹어 컴파일오류가 생긴다. 다음은 원본 소스중 수정하여 만든 date 및 dated 클래스를 사용한 example이다.(복원한 클래스는 다운로드하도록 해두었다)
#include <iostream>
#include "dated.h"

using namespace std;

void examples_date();
void example_date_simple();
void example_date_comparisons();
inline void dates_comparisons(date d1, date d2);

void examples_dated();

int main()
{
examples_date();
cout<<"------------------------------------"<<endl;
examples_dated();
return 0;
}

void examples_date() {
cout << "TESTING DATE " << endl;
example_date_simple();
cout<<"------------------------------------"<<endl;
example_date_comparisons();
cout << "DONE TESTING DATE " << endl;
};

void example_date_simple(){
cout << "TESTING DATE SIMPLE " << endl;
cout << " construction: date(1,1,1998):" << date(1,1,1998) <<endl;
cout << " increment: ++date(1,1,1998):" << ++date(1,1,1998) << endl;
cout << " decrement: --date(1,1,1998):" << --date(1,1,1998) << endl;
date d(1,1,2006);
cout << "valid date(1,1,2006) ?" << date(1,1,2006).valid() << endl;
cout << "valid date(33,1,2006) ?" << date(33,1,2006).valid() << endl;
cout << "DONE TESTING DATE SIMPLE " << endl;
}

void example_date_comparisons(){
cout << "TESTING DATE COMPARISONS " << endl;
date d1(25,7,1993);
date d2(8,10,1993);
dates_comparisons (d1,d2);
dates_comparisons (d1,d1);
cout << "DONE TESTING DATE COMPARISONS " << endl;
};

inline void dates_comparisons(date d1, date d2) {
cout <<"COMPARISON TEST" << endl;
cout << " Comparing " << d1 << "and" << d2 << endl;
cout << " is" << d1 <<"equal to " << d2 ;
if (d1==d2){ cout << "YES"; } else { cout << "NO"; };
cout << endl;
cout << " is" << d1 <<"different from" << d2 ;
if (d1!=d2){ cout << "YES"; } else { cout << "NO"; };
cout << endl;
cout << " is" << d1 <<"less than " << d2 ;
if (d1<d2){ cout << "YES"; } else { cout << "NO"; };
cout << endl;
cout << " is" << d1 <<"greater than " << d2 ;
if (d1>d2){ cout << "YES"; } else { cout << "NO"; };
cout << endl;
};

void examples_dated(){
cout << "TESTING dated<> simple " << endl;
dated<double> dd;
date d=date(1,1,1998);
dd.insert(d,1);
d = date(1,2,1998);
dd.insert(d,2);
cout << dd.size() << " elements " << endl;
cout << dd ;
cout << " inserting at 1/1 and 1/3 " << endl;
dd.insert(date(1,1,1998),0.5);
dd.insert(date(1,3,1998),3);
cout << dd;
cout << " deleting 1/2" << endl;
dd.remove(date(1,2,1998));
cout << dd;
cout << " dated<string> " << endl;
dated<string> ds;
ds.insert(date(1,1,1998),"A");
ds.insert(date(1,2,1998),"B");
cout << ds;
cout << "DONE test dated<>" << endl;
};

위의 main.cpp 실행결과

TESTING DATE
TESTING DATE SIMPLE
construction: date(1,1,1998): 19980101
increment: ++date(1,1,1998): 19980102
decrement: --date(1,1,1998): 19971231
valid date(1,1,2006) ?1
valid date(33,1,2006) ?0
DONE TESTING DATE SIMPLE
------------------------------------
TESTING DATE COMPARISONS
COMPARISON TEST
Comparing 19930725 and 19931008
is 19930725 equal to 19931008 NO
is 19930725 different from 19931008 YES
is 19930725 less than 19931008 YES
is 19930725 greater than 19931008 NO
COMPARISON TEST
Comparing 19930725 and 19930725
is 19930725 equal to 19930725 YES
is 19930725 different from 19930725 NO
is 19930725 less than 19930725 NO
is 19930725 greater than 19930725 NO
DONE TESTING DATE COMPARISONS
DONE TESTING DATE
------------------------------------
TESTING dated<> simple
2 elements
19980101 1
19980201 2
inserting at 1/1 and 1/3
19980101 0.5
19980201 2
19980301 3
deleting 1/2
19980101 0.5
19980301 3
dated<string>
19980101 A
19980201 B
DONE test dated<>

Process returned 0 (0x0) execution time : 0.029 s
Press any key to continue.

[DOWNLOAD]date_dated_class.zip(date와dated클래스를 정리)

by 타임버드 | 2012/01/30 11:20 | C/C++/C# | 트랙백 | 덧글(0)

OCAML 삽질로그

        Objective Caml version 3.12.1

# ['a','b','c'];; char타입의 리스트 생성
- : (char * char * char) list = [('a', 'b', 'c')]
# ['abc'];; abc는 char가 아닌 string타입이므로 싱글이 아닌 더블쿼테이션(")을 사용한다
Characters 1-2:
['abc'];;
^
Error: Syntax error
# ['abc','def'];;
Characters 1-2:
['abc','def'];;
^
Error: Syntax error
# ['a','def'];;
Characters 5-6:
['a','def'];;
^
Error: Syntax error
# "abcd".[2];; 문자열에서 2번 인덱스 꺼내기
- : char = 'c'
# String.make 1 'a';; 문자열 만들기(String.make translates your character to a string
- : string = "a"
# String.make 1 'ab';;
Characters 14-15:
String.make 1 'ab';;
^
Error: Syntax error
# 'abc'^'def'
;;
Characters 0-1:
'abc'^'def'
^
Error: Syntax error
# "abc" ^ "def";; 문자열 연결
- : string = "abcdef"
# ["abc","def"];; 문자열 리스트
- : (string * string) list = [("abc", "def")]
# let l=["abc","def"];;
val l : (string * string) list = [("abc", "def")]
# l;; 앞서 만든 문자열 리스트 출력
- : (string * string) list = [("abc", "def")]
# l::[];;
- : (string * string) list list = [[("abc", "def")]]
# let rec join sep l= 리스트의 항목을 구분자(sep)를 붙여 join함수를 만든다
match l with
| []->""
| x::[]->x
| x::xs->x^sep^join sep xs;;
val join : string -> string list -> string =
# join "/" ["a";"b"];;
- : string = "a/b"
# let join1 sep=function 더 간결한 join함수를 만듬. 그러나 재귀호출을 위한 rec를 빼먹어서 에러
| []->""
| x::[]->x
| x::xs->x^sep^join1 sep xs;;
Characters 64-69:
| x::xs->x^sep^join1 sep xs;;
^^^^^
Error: Unbound value join1
# let rec join1 sep=function
| []->""
| x::[]->x
| x::xs->x^sep^join1 sep xs;;
val join1 : string -> string list -> string =
# join1 "?" ["abc";"def"];; 새로운 join함수 성공
- : string = "abc?def"
#
세상에는 별 희한한 언어가 있는데, ocaml이 어떤 용도로 협업에 쓰는 지는 모르지만, lisp만큼이나 까다로운 듯

by 타임버드 | 2012/01/27 08:58 | 트랙백 | 덧글(0)

◀ 이전 페이지          다음 페이지 ▶