파일 로깅 기능 추가.

GHTS 2023. 1. 10. 20:22 Posted by UnHa Kim

콘솔창을 닫으면 실행 기록이 사라져 버리고 이후 문제가 발생한 원인을 추적하는 데 애를 먹은 후,

콘솔창 출력 문자열을 파일에 동시에 저장하는 기능을 추가했다.

 

main() 함수 초반부에 다음과 같이 실행하면 해당 기능을 사용할 수 있다.

 

lib.F로그_설정_화면_파일_동시()
defer lib.F로그_파일_닫기()

 

lib.F문자열_출력(), lib.F에러_출력(), lib.New에러with출력()등의 함수에서 화면에 출력하는 내용이 'log_<연월일시분초>.txt' 파일에 저장된다.

1달이 지난 로그 파일은 삭제하여 저장공간을 꽉 채워서 문제가 생기는 현상을 미연에 방지해 놓았다.

 

 

'GHTS' 카테고리의 다른 글

호가 단위 변경  (0) 2023.01.10
T8410 TR 추가.  (0) 2023.01.10
Xing API 초기화 문제 해결 (MsgPack -> Gob)  (2) 2022.11.02
야후! 금융 재무 정보 얻기.  (0) 2022.10.08
해외 주식 API. (한국투자증권 Open API)  (0) 2022.01.21

호가 단위 변경

GHTS 2023. 1. 10. 20:09 Posted by UnHa Kim

2023년부터 새로운 호가 단위가 적용된다.

 

이에 대응하는 코드는 작년 11월경에 미리 작성해 두었으나, 당시 언론기사에 나온 기준과 2023년부터 실제로 적용된 기준이 미세하게 달라서, 에러가 발생하는 것을 발견하고, 현재 기준에 맞게 수정했다.

 

며칠 전 이미 적용된 내용이지만, 블로그에 기록해 두는 것을 깜빡하고 있다가 뒤늦게 올린다.

'GHTS' 카테고리의 다른 글

파일 로깅 기능 추가.  (0) 2023.01.10
T8410 TR 추가.  (0) 2023.01.10
Xing API 초기화 문제 해결 (MsgPack -> Gob)  (2) 2022.11.02
야후! 금융 재무 정보 얻기.  (0) 2022.10.08
해외 주식 API. (한국투자증권 Open API)  (0) 2022.01.21

T8410 TR 추가.

GHTS 2023. 1. 10. 20:05 Posted by UnHa Kim

그동안 일일 가격 정보 수집에 T8413 TR을 애용해 왔으나,

2023년 1월 5일에 이베스트투자증권 API게시판에 올라온 공지에 따르면 T8413 TR은 종가가 수정종가로 바뀌고, 게다가 이후 삭제될 예정이라고 한다.

대체품으로 새로 생긴 TR이 'T8410'이다.

 

'T8410'은 수정주가 적용 여부를 선택할 수 있고, 연봉 데이터도 제공한다는 점에서 기능 개선이 있다.

xing.util 패키지 내 일일 가격 정보 수집 기능에서 (T8413 대신) T8410을 사용하도록 수정했다.

 

'GHTS' 카테고리의 다른 글

파일 로깅 기능 추가.  (0) 2023.01.10
호가 단위 변경  (0) 2023.01.10
Xing API 초기화 문제 해결 (MsgPack -> Gob)  (2) 2022.11.02
야후! 금융 재무 정보 얻기.  (0) 2022.10.08
해외 주식 API. (한국투자증권 Open API)  (0) 2022.01.21

Xing API 초기화 문제 해결 (MsgPack -> Gob)

GHTS 2022. 11. 2. 22:20 Posted by UnHa Kim

Go 1.19로 업그레이드 이후 MsgPack 변환을 위한 외부 의존성 라이브러리(github.com/ugorji/go/codec)에서 종종 에러가 발생하였다.

해당 라이브러리 개발자는 깃허브 issue의 버그 보고에 대응을 제대로 못하고 있다.

 

이 문제를 해결하기 위해서 문제를 일으키는 외부 코드에 대한 의존성을 삭제하기로 했다.

Go언어에는 'Gob'이라는 변환 기능이 내장되어 있다. (참고 : https://pkg.go.dev/encoding/gob)

Gob은 MsgPack보다 범용성/호환성은 떨어지지만, 사용 편의성과 성능에서 크게 뒤처지지 않는다.

 

MsgPack 변환을 이용하는 모든 기능을 Gob변환 형식으로 바꾸어서 외부 코드를 더 이상 사용하지 않도록 하니 더 이상 에러가 발생하지 않는다.

대신, ghts/xing/dll32 패키지는 Go언어에서만 사용할 수 있게 제한되었다.

하지만, 아마도 다른 언어에서 dll32 패키지만 쏙 빼서 사용하는 경우는 무척 드물 것이므로 크게 문제 되지는 않을 것으로 예상된다.

 

'GHTS' 카테고리의 다른 글

호가 단위 변경  (0) 2023.01.10
T8410 TR 추가.  (0) 2023.01.10
야후! 금융 재무 정보 얻기.  (0) 2022.10.08
해외 주식 API. (한국투자증권 Open API)  (0) 2022.01.21
C언어 컴파일러 의존성 제거.  (8) 2021.07.10

야후! 금융 재무 정보 얻기.

GHTS 2022. 10. 8. 13:46 Posted by UnHa Kim

다음 동영상에 '야후! 금융'에서 재무 정보를 추출하는 방법이 잘 설명되어 있다.

https://youtu.be/fw4gK-leExw

 

동영상 내용이 파이썬 기준이지만, 내용만 이해하면 Go언어에서도 구현은 쉽다.

chromedp(https://github.com/chromedp/chromedp) 모듈을 사용하면 자바스크립트를 이용해서 동적으로 생성되는 '야후! 금융' 웹페이지도 문제없이 불러들일 수 있다.

이렇게 읽어온 HTML에서 JSON 데이터 부분만 추출해서 map형태로 저장한 후 적절히 활용하면 된다.

애플의 재무 데이터를 읽어들이는 Go언어 예제 코드는 다음과 같다.

package main

import (
	"context"
	"encoding/json"
	"fmt"
	"github.com/chromedp/chromedp"
	"log"
	"regexp"
	"testing"
	"time"
)

// 참고자료 : https://youtu.be/fw4gK-leExw
// 애플 재무 정보 수집 예제
func main() {
	const url템플릿 = `https://finance.yahoo.com/quote/%v/financials`
	종목코드 := "AAPL" // 애플

	// create chrome instance
	ctx, cancel := chromedp.NewContext(context.Background())
	defer cancel()

	// create a timeout
	ctx, cancel = context.WithTimeout(ctx, 30*time.Second)
	defer cancel()

	var html string
	url := fmt.Sprintf(url템플릿, 종목코드)

	if err := chromedp.Run(ctx,
		chromedp.Navigate(url),
		chromedp.InnerHTML("body", &html, chromedp.ByQuery),
	); err != nil {
		log.Fatal(err)
	}

	// HTML에서 JSON 데이터를 맵 형태로 추출
	html = regexp.MustCompile(`(?s)\s--\sData\s--\s.+?</script>`).FindString(html)
	html = regexp.MustCompile(`(?s)root.App.main.+</script>`).FindString(html)
	html = html[16 : len(html)-21]

	var 맵 map[string]interface{}

	json.Unmarshal([]byte(html), &맵)

	손익계산서_연도 := f2맵_모음(맵, []string{"context", "dispatcher", "stores", "QuoteSummaryStore", "incomeStatementHistory", "incomeStatementHistory"})
	f맵_모음_출력("손익계산서_연도", 손익계산서_연도)

	손익계산서_분기 := f2맵_모음(맵, []string{"context", "dispatcher", "stores", "QuoteSummaryStore", "incomeStatementHistoryQuarterly", "incomeStatementHistory"})
	f맵_모음_출력("손익계산서_분기", 손익계산서_분기)

	재무상태표_연도 := f2맵_모음(맵, []string{"context", "dispatcher", "stores", "QuoteSummaryStore", "balanceSheetHistory", "balanceSheetStatements"})
	f맵_모음_출력("재무상태표_연도", 재무상태표_연도)

	재무상태표_분기 := f2맵_모음(맵, []string{"context", "dispatcher", "stores", "QuoteSummaryStore", "balanceSheetHistoryQuarterly", "balanceSheetStatements"})
	f맵_모음_출력("재무상태표_분기", 재무상태표_분기)

	현금흐름표_연도 := f2맵_모음(맵, []string{"context", "dispatcher", "stores", "QuoteSummaryStore", "cashflowStatementHistory", "cashflowStatements"})
	f맵_모음_출력("현금흐름표_연도", 현금흐름표_연도)

	현금흐름표_분기 := f2맵_모음(맵, []string{"context", "dispatcher", "stores", "QuoteSummaryStore", "cashflowStatementHistoryQuarterly", "cashflowStatements"})
	f맵_모음_출력("현금흐름표_분기", 현금흐름표_분기)
}

func f2맵_모음(맵 map[string]interface{}, 키_모음 []string) (맵_모음 []map[string]interface{}) {
	for _, 키 := range 키_모음 {
		if 맵2, ok := 맵[키].(map[string]interface{}); ok {
			맵 = 맵2
			continue
		} else if 값_모음, ok := 맵[키].([]interface{}); ok {
			맵_모음 = make([]map[string]interface{}, len(값_모음))

			for i, 값 := range 값_모음 {
				맵_모음[i] = 값.(map[string]interface{})
			}

			return 맵_모음
		} else {
			panic(fmt.Errorf("예상하지 못한 자료형 %T\n", 맵[키]))
		}
	}

	return
}

func f맵_모음_출력(제목 string, 맵_모음 []map[string]interface{}) {
	for i, 맵 := range 맵_모음 {
		for 키, 값 := range 맵 {
			fmt.Printf("%v %v %v %v\n", 제목, i, 키, 값)
		}
	}
}

 

 

 

 

'GHTS' 카테고리의 다른 글

T8410 TR 추가.  (0) 2023.01.10
Xing API 초기화 문제 해결 (MsgPack -> Gob)  (2) 2022.11.02
해외 주식 API. (한국투자증권 Open API)  (0) 2022.01.21
C언어 컴파일러 의존성 제거.  (8) 2021.07.10
GHTS 개략 설명  (13) 2021.01.13

해외 주식 API. (한국투자증권 Open API)

GHTS 2022. 1. 21. 18:56 Posted by UnHa Kim

그동안 이베스트투자증권의 Xing API를 이용해서 국내 주식만 매매해 왔다.

한국 증시는 부진을 거듭하는 반면, 해외 증시(특히, 미국 증시)는 상승세를 이어가는 걸 보면서,

한국 주식 시장에만 투자하는 것은 분산 투자 면에서도 별로 좋은 생각이 아니라는 것을 깨달았다.

그리하여, 해외 주식 투자도 가능한 API를 찾던 중 발견한 게 

한국투자증권의 Open API이다. ('efriend Expert'로 검색해도 된다.)

 

API 기능을 설명하는 'efriend Expert Viewer'의 화면 일부를 캡쳐했는 데,

미국 뿐만 아니라, 중국, 일본 주식도 매매가 가능한 것을 알 수 있다.

문제는 이게 OCX형태로 구현되어 있어서 Go언어에서는 사용하기 무척 까다롭다는 것이다.

 

그렇다고 해서 모든 로직을 C#으로 옮겨가려고 하니, 정든 Go언어를 손에서 내려놓고 싶지 않다.

결국, OCX호출에 편한 C#로 API를 호출하는 독립된 프로세스를 두고,

Go언어로 작성된 매매 전략 모듈에서 윈도우 소켓을 통해서 호출하는 구조를 구상 중이다.

(투자 교육 때 뵌 현직 옵션 시스템 트레이더 분에게서 윈도우 소켓 프로그래밍에 대해서 들었던 게 중요한 힌트가 되었다.)

 

역시 끊임없이 삽질을 거듭하다보면 길을 찾게 되는 것 같다.

 

'GHTS' 카테고리의 다른 글

Xing API 초기화 문제 해결 (MsgPack -> Gob)  (2) 2022.11.02
야후! 금융 재무 정보 얻기.  (0) 2022.10.08
C언어 컴파일러 의존성 제거.  (8) 2021.07.10
GHTS 개략 설명  (13) 2021.01.13
어제, 오늘, 금일, 당일, 전일.  (0) 2019.10.10

C언어 컴파일러 의존성 제거.

GHTS 2021. 7. 10. 06:55 Posted by UnHa Kim

GHTS는 과거 이베스트 증권사 API를 호출할 때

C언어를 통한 cgo방식(https://blog.golang.org/cgo)으로 하다가,

Go언어를 통한 DLL 방식(https://github.com/golang/go/wiki/WindowsDLLs)으로 갈아타면서,

2021년 1월경, 거의 모든 C언어 코드를 Go언어 코드로 대체하였다.

 

그러나, 몇몇 cgo특수 함수(C.GoBytes()등)가 남아 있어서 

GHTS를 사용하려면 여전히 C언어 컴파일러가 필요했고,

이는 GHTS를 처음 사용하는 사람에게 설치 난이도를 높이는 진입 장벽으로 작용하였다.

 

오늘 드디어 마지막 남은 cgo 특수 함수를 대체해서

더 이상 C언어 컴파일러를 설치하지 않아도 GHTS를 사용할 수 있게 되었다.

 

구글을 조금만 더 열심히 검색했더라면 금방 해결책을 찾을 수 있었을 텐데,

괜히 혼자 해결책 궁리하다가 너무 오래 걸린 것 같아서 아쉽긴 하지만,

뒤늦게라도 사용 편의성을 향상할 수 있어서 다행스럽다.

 

노하우가 중요한 시대가 아니라

적절한 구글 검색어를 생각해 내는 게 중요한 시대가 되었다는 것을 다시 한 번 실감한다.

 

 

 

 

'GHTS' 카테고리의 다른 글

야후! 금융 재무 정보 얻기.  (0) 2022.10.08
해외 주식 API. (한국투자증권 Open API)  (0) 2022.01.21
GHTS 개략 설명  (13) 2021.01.13
어제, 오늘, 금일, 당일, 전일.  (0) 2019.10.10
소스코드 패키지 통합  (0) 2019.07.27

GHTS 개략 설명

GHTS 2021. 1. 13. 18:56 Posted by UnHa Kim

국내 증권사의 API는 모두 32비트에서만 호출 가능합니다.

32/64비트 경계를 넘어서 OLE/OCX 간단한 호출하는 방법이 인터넷에 나와있지만,
증권사 API 호출 결과를 넘겨받는 데 필요한 'OLE 이벤트'는 작동하지 않더군요.
그래서, API 호출은 무조건 32비트 프로세스에서 해야 합니다.

(DLL, OLE, OCX 무관하게 32비트이어야 합니다.)

매매 전략 구동을 비롯한 모든 코드를 32비트로 실행해도 괜찮다면,

별도의 프로세스로 분리하지 않고 단일 프로세스 내에서 사용하면 간단하고 좋습니다.

 

그러나, 여하한 이유로 매매 전략을 64비트 프로세스에서 운용해야 한다면

증권사 API 호출을 독립된 32비트 프로세스로 분리한 후 상호 연동 시켜야 합니다.

 

GHTS에서는 다수의 매매 전략을 동시에 운용하는 상황을 상정하고 작성되었습니다.

모든 동시 다중 처리는 디버깅하기 몹시 까다롭기로 유명한

데이터 동시 액세스 충돌(이하 데이터 레이스) 버그 발생 가능성이 상존합니다.

Go언어에서는 이러한 버그를 추적할 수 있는 '레이스 감지기'를 제공하지만 64비트에서만 지원됩니다.

golang.org/doc/articles/race_detector.html

 

매매 시스템의 안정적인 운용을 위해서는

데이터 레이스 상황을 적절하게 디버깅 할 수 있어야 하기에

매매 전략을 64비트 프로세스에서 실행할 수 있어야 한다고 결정했으며,

증권사 API를 호출하는 기능을 별도의 32비트 프로세스로 분리했습니다.

 

그 과정에서 32비트 프로세스와 64비트 프로세스 간 자료교환을 위한 기술적인 문제는 다음과 같이 해결했습니다.

1. Go 자료형을 []byte로 변환
https://pkg.go.dev/encoding/gob

2. []byte 로 변환된 데이터를 전송 및 수신
https://github.com/nanomsg/mangos

RPC로 데이터를 전송하려면 우선 []byte로 변환하는 게 필요한 데, Go언어에는 Gob이라는 내장 변환 기능이 존재합니다.


이렇게 []byte로 변환된 데이터를 프로세스끼리 주고 받도록 해주는 기술로 가장 유명한 게 ZeroMQ입니다.

GHTS도 초반에는 ZeroMQ를 사용했습니다만,

ZeroMQ는 컴파일이 느리기로 유명한 C++언어로 작성된 관계로

ZeroMQ를 적용한 이후 컴파일이 느려져서 전체적인 개발 생산성에 큰 타격을 입었습니다.

 

이를 해결하기 위해서 비슷한 기능을 가진 nanomsg의 순수한 Go언어 구현체인 mangos를 선택했습니다.
https://github.com/nanomsg/mangos

이상 GHTS의 내부 구조가 지금처럼 분리된 이유와

이를 위해서 사용하는 의존성 라이브러리를 선택하게 된 이유를 간략히 설명드렸습니다.

어제, 오늘, 금일, 당일, 전일.

GHTS 2019. 10. 10. 12:17 Posted by UnHa Kim

간단한 용어이지만 혼동을 유발하는 경우가 있어서 메모해 놓는다.

 

금일, 어제는 주말, 공휴일등 모든 일자를 포함해서 지칭하지만,

 

주식매매에서 '당일', '전일'은 증시 개장일만 고려해서 지칭한다.

 

 

- 당일 : 가장 최근 영업일.

 

- 전일 : 당일 이전 가장 최근 영업일.

 

금일이 개장일이면 '당일 == 금일'이다.

 

금일이 (주말, 공휴일 기타 이유로) 개장일이 아니면 '당일 != 금일'.

 

 

간단하지만 혼동되는 용어라서 정리를 해 보았다.

 

 

'GHTS' 카테고리의 다른 글

C언어 컴파일러 의존성 제거.  (8) 2021.07.10
GHTS 개략 설명  (13) 2021.01.13
소스코드 패키지 통합  (0) 2019.07.27
Xing API 현물 주식 주문 TR 테스트 완료.  (0) 2018.06.25
Xing API에 숨겨진 지뢰 3  (0) 2018.06.07

소스코드 패키지 통합

GHTS 2019. 7. 27. 10:02 Posted by UnHa Kim

Go언어에서 GOPATH 의존성 시스템에서 Go모듈(Module) 시스템으로 넘어가면서,

 

그간 각각의 독립된 패키지에서 개발하던 기능들을

 

하나의 패키지로 모두 통합하고,

 

각각의 기능은 서브디렉토리에 분류하게 되었다.

 

 

GHTS 라이브러리를 불러다 쓰는 입장에서도

 

Go모듈 방식을 채용할 경우 버전 관리등이 한결 편해질 것으로 예상된다.

 

예전에 개발하던 개별 패키지들은 모두 삭제했으며,

 

통합된 패키지의 주소는 다음과 같다.

 

https://github.com/ghts/ghts

 

 

'GHTS' 카테고리의 다른 글

GHTS 개략 설명  (13) 2021.01.13
어제, 오늘, 금일, 당일, 전일.  (0) 2019.10.10
Xing API 현물 주식 주문 TR 테스트 완료.  (0) 2018.06.25
Xing API에 숨겨진 지뢰 3  (0) 2018.06.07
Xing API에 숨겨진 지뢰 2  (0) 2018.06.07