ic


흔히 보는 특별하지 않은 엑셀 팁 EXCEL/VBA

흔하게 만나는 엑셀팁인데, 지난 번 모대학교 파생상품금융 강의에서 지루한 시간을 때우기 위해 준비한 것입니다. 지루한 강의실습중 단비같은 팁을 만나면 눈이 반짝 반짝거리더군요. (움직이는 GIF(일명 움짤)을 만들었는데, 이글루스 모바일 앱에선 첫 장만 보입니다)

[DOWNLOAD]timebird_exccel_tips.pdf

믿을 수 없는 숫자놀음 증권

xing API를 사용하고 있는 데, 기술적 지표를 따로 제공해준다. 사실 기술적 지표 공식들이 그리 어려운 수준은 아니지만 일일이 만들기엔 귀찮다. 수고를 덜어 준다니 얼마나 반가운 일인가? 만든 프로그램으로 지표를 화면에 띄워 놓고, 동시에 스마트폰앱으로 지표를 보니 뭔가 이상하다. 동일종목, 동일지표, 동일한 지표매개변수, 동일한 시간주기인데, 값이 큰 차이가 난다. 귀찮아서 작은 차이라면 무시할텐데..증권사 홈페이지에 이런 문의가 있으리라 생각되어 게시판을 보니, 역시 여러 사람들이 그런 문제를 질의한 모양이다.

안녕하세요. 관리자입니다.
당사 API의 차트는 xing차트(4201,4301) 과 동일한 지표계산을 합니다. STAR 차트 지표와는 계산에서 차이가 있을 수 있습니다. 비교하신 차트가 STAR차트라면, xing차트와 같은 지표로 확인 부탁드립니다. 이용에 참고하시기 바랍니다.

그러나 답변을 한 관리자의 답변과 달리 4201/4301차트 역시 샘플로 준 엑셀파일과 다른 결과를 보여준다. 아무래도 계산을 직접 해야겠다. 현재 30분봉은 아직 미완성이라 그러다고 쳐도 지난 봉의 결과가 다르다는 사실은 현재의 분봉이 결국 API와 다를 것이다. 그런데 xing API가 리눅스를 지원하는 듯하다. 리눅스 API를 신청한다는 게시물이 보인다. 공지사항에서 보질 못했는데...

우리가 몰랐던, 아니 자주 사용하지 않던 데이터구조체 EXCEL/VBA

vba에서 자주 사용하는 데이터구조체는 배열, 딕셔너리, 컬렉션 등이다. 하지만 너무 단순한 것들이라 가끔 불편하지만, 익숙해서 그냥 쓰고 있다. 간만에 vba에서 큐, 스택 같은 구닥다리부터 최신식 구조체(사실 Object Container) 몇 가지를 해시테이블만 빼고 대거 방출하고자 한다.
해시테이블 예제를 만들려니 왕귀찬...
Sub demoArrayList() 
Dim arrList As Object
Dim item

'Create the ArrayList
Set arrList = CreateObject("System.Collections.ArrayList")

arrList.Add "Hello"
arrList.Add "You"
arrList.Add "There"
arrList.Add "Man"
arrList.Remove "Man"

'Get number of items
Debug.Print arrList.Count 'Result: 3

For Each item In arrList
Debug.Print item
Next

End Sub

Sub demoSortedList()
Dim sortedList As Object

' Create the SortedList
Set sortedList = CreateObject("System.Collections.SortedList")

sortedList.Add "ThisortedListrd", "!"
sortedList.Add "Second", "World"
sortedList.Add "First", "Hello"

' Displays the properties and values of the SortedList.
Debug.Print "Count:"; sortedList.Count
Debug.Print "Capacity:"; sortedList.Capacity

Dim i As Long

For i = 0 To sortedList.Count - 1
Debug.Print sortedList.GetKey(i), sortedList.GetByIndex(i)
Next
End Sub

Sub demoQueue()
Dim queue As Object
Dim peekAtFirst, doesContain, firstInQueue

'Create the Queue
Set queue = CreateObject("System.Collections.Queue")

queue.Enqueue "Hello"
queue.Enqueue "There"
queue.Enqueue "Mr"
queue.Enqueue "Smith"

peekAtFirst = queue.Peek() 'Result" "Hello"
Debug.Print peekAtFirst

doesContain = queue.Contains("htrh") 'Result: False
Debug.Print doesContain

doesContain = queue.Contains("Hello") 'Result: True
Debug.Print doesContain

'Get first item in Queue and remove it from the Queue
firstInQueue = queue.Dequeue() '"Hello"
Debug.Print firstInQueue

'Count items
Debug.Print queue.Count 'Result: 3

'Clear the Queue
queue.Clear

Set queue = Nothing
End Sub

Sub demoStack()
Dim stack As Object
Dim peekAtTopOfStack, doesContain, topStack

'Create Stack
Set stack = CreateObject("System.Collections.Stack")

stack.Push "Hello"
stack.Push "There"
stack.Push "Mr"
stack.Push "Smith"

peekAtTopOfStack = stack.Peek()
Debug.Print peekAtTopOfStack

doesContain = stack.Contains("htrh") 'Result: False
Debug.Print doesContain

doesContain = stack.Contains("Hello") 'Result: True
Debug.Print doesContain

'Get item from the top of the stack (LIFO)
topStack = stack.Pop() 'Result: "Smith"
Debug.Print topStack

'Clear the Stack
stack.Clear

Set stack = Nothing
End Sub
[참고]MSDN-Early Binding이 아니라서(못해서) VBE에서 편리하게 클래스의 멤버함수나 속성을 알 수 없으니 MSDN을 참조해가며 익히는 게 좋을 것이다.
1. ArrayList
2. SortedList
3. Hashtable
4. Stack
5. Queue

변동성을 이용한 페어 트레이딩 전략 증권

페어트레이딩전략은 평균회귀(Mean-Reversion)의 성질을 이용한 매매전략이다. 주식의 경우 동종업종내 종목을 가지고 하는 경우가 많은 데, 주식은 공매도가 까다로워 그리 재미있진 못하다. 그런데 페어트레이딩전략에는 그게 전부는 아니다. 변동성을 이용한 페어트레이딩 전략도 있는데, 단기변동성이 장기변동성보다 커서 차익거래의 기회가 존재한다(Lo and MacKinlay 1988).


[DOWNLOAD]VolArb_Summary.pdf

워크시트 출력에 대한 고민-배열의 출력 EXCEL/VBA

vba를 이용하여 워크시트에 출력하는 일은 거의 필수적인 작업이다. 그런데 출력하는 작업은 vba의 속도를 떨어 뜨리는 주범중 하나이다. 그래서 추천하는 방법이 하나의 루프에서 100번을 반복하면서 100번을 출력하는 것보다는 배열에 저장하고, 루프를 나오면 한번에 출력하는 것이다.

그런데 10,000개의 데이터를 워크시트에 한번에 출력하는 게 문제이다. Range("B2") = mat()는 B2셀에 배열의 (1,1)의 값을 출력한다.
Sub CopyMatrixToRange()
Dim mat(10, 10) As Double
Dim i As Long, j As Long

Randomize
For i = LBound(mat) To UBound(mat)
For j = LBound(mat, 2) To UBound(mat, 2)
mat(i, j) = Rnd
Next
Next
Sheet1.Range("B2") = mat()
End Sub
이런 오류를 해결하고 아래와 같이 출력하려면

아래와 같이 출력하려는 배열의 크기만큼 셀의 범위를 맞춰야 한다. 아래의 코드에서 10x10의 배열을 출력하기 위해 셀의 범위를 B2:K11 로 맞춰야 한다.
Sub CopyMatrixToRange()
Dim mat(10, 10) As Double
Dim i As Long, j As Long

Randomize
For i = LBound(mat) To UBound(mat)
For j = LBound(mat, 2) To UBound(mat, 2)
mat(i, j) = Rnd
Next
Next
Sheet1.Range("B2:K11") = mat()
End Sub
그런데 배열의 크기에 맞춰 셀 범위를 하드코딩해두는 건 그리 아름다운 모습은 아니다. 그래서 배열의 크기만큼 셀 범위를 자동으로 맞출 필요가 있고, 크기를 계산할 필요가 있다. 아래의 코드에서 Range개체의 Resize()메서드와 UBound()/LBound()함수를 이용하여 행과 열의 크기를 계산하였다.
Sub CopyMatrixToRange()
Dim mat(10, 10) As Double
Dim i As Long, j As Long

Randomize
For i = LBound(mat) To UBound(mat)
For j = LBound(mat, 2) To UBound(mat, 2)
mat(i, j) = Rnd
Next
Next

Dim cntRow As Long, cntCol As Long

cntRow = UBound(mat) - LBound(mat) + 1
cntCol = UBound(mat, 2) - LBound(mat, 2) + 1


Sheet1.Range("B2").Resize(cntRow, cntCol) = mat()
End Sub
하지만 1억개의 셀에 출력하는 것은 버거운지 약간 시간이 걸리지만 루프를 돌리는 것보단 훨씬 낫다.

부처님과 리스크 증권

부처님의 전생설화, 본생경(本生經)은 바로 부처님의 전생이야기다. 무려 547편의 전생이야기를 모아 된 것으로 다음과 같은 이야기가 있다.

많은 상인들이 무리를 지어 이곳 저곳을 돌며 장사를 하고 있었다. 장사를 하러 돌아다니던 중 멀리 마을이 보이고 그들의 우두머리는 바로 마을에 들어가지 않고 선발대를 먼저 떠나 보내며 당부를 하였다.

과거에 먹어 보지 못한 음식이나 나무 열매 등을 절대로 먹지 마라


선발대가 마을에 도착해보니 큰 나무가 있었는데, 너무나 맛있게 보이는 열매들이 주렁주렁 매달려 있었다. 우두머리의 말을 무시하고 선발대의 몇몇은 열매을 따 먹었다. 나중에 마을에 도착한 우두머리가

그 나무의 열매에는 독이 있다


라고 말했다. 과일을 먹은 일부는 먹은 것을 토해내 겨우 목숨을 건지고 이미 너무 많이 먹은 일부는 죽고 말았다. 사실 마을사람들은 이런 식으로 목숨을 잃은 사람들의 물건을 빼앗고 있었다. 상인의 우두머리에게 ‘어떻게 독이 있는 지 아셨습니까?’ 라고 묻자, 그는

마을 입구 나무에 나지막한 가지에 열매들이 잘 익어 있는데,
아무도 따먹지 않고 있다면 독이 있다고 봐야지


라고 대답하였다.

겉보기에 먹음직 스러워 보이지만 아무도 먹지 않는 과일처럼 누군가가 큰 위험부담없이 고수익을 올릴 수 있는 금융상품을 권유한다면 그 진실성을 의심해봐야 한다. 위험을 감수하지 않으면서 고수익을 올릴 수 는 없다.

리스크의 뜻은 손실에 노출될 가능성을 말한다. 보통 리스크를 위험이라고 번역을 하지만 정확히 말하는 위험(danger)이 아니다.

출처:옵션가격이론:금융시장의 수학적 모델, 카이스트 수학과 최건호



New comment on 'Python as an Excel scripting language' EXCEL/VBA

지난 번 포스팅(뭐? python을 엑셀에서 사용할 수 있다고?)에서 엑셀 스크립트언어로서 파이썬이 채택될거라는 소문을 전해드렸는데, 오늘 오전에 office.com에서 사용자들의 의견을 전해주는 메일을 보내주었더군요.  메일 내용에 따르면 코멘트를 올린 사용자는 대기업에서 일하는데, 예전엔 엑셀로 많은 일을 해왔는데, 지금은 파이썬으로 그 일들을 대체하고 있다고 하네요.  그러나 파이썬이 엑셀 스크립팅 언어가 된다면 그런 추세가 반전될거라는 조언입니다. 그런 상황이 온다면 재미있는 일이 많이 생길 듯합니다. 일단 블로그 포스팅과 책을 써야 할 것 같군요. 그리고 엑셀을 이용한 기계학습/딥러닝도 돌려보고요..





한 번만 실행하는 루틴 EXCEL/VBA

하나의 매매 알고리즘을 만들면서 알고리즘을 하나의 프로시저에 몰아넣다 보니, 곤란한 점이 생긴다. 실시간 시세가 수신될때마다 이 알고리즘을 호출해야 하는 데, 구현된 알고리즘에는 처음 한 번만 실행하는 투자자원배분 루틴이 있다. 그렇다면 알고리즘을 두 개의 프로시저로 분리하는 게 맞다. 하지만 이러다 보니 두 개의 프로시저에서 참조하는 변수를 전역변수로 해야 한다. 전역변수는 되도록 줄이는 게 좋다. 전역변수의 갯수가 많으면 관리하기 어려워 질 수 있다.

이럴 경우 이전의 실행여부를 어디에 저장해두고(보통 워크시트 구석의 어느 셀), 그 정보를 읽어와서 실행여부를 결정할 수 있다. 그런 방법은 이미 흔한 것이라 생략하고 다음과 같이 2가지 방법을 생각해볼 수 있다.

1) Static 사용
보통의 프로시저 수준의 로컬변수는 프로시저 종료와 함께 그 생명을 다하지만 "Static" 변수는 프로젝트가 종료될때 까지 살아남는다,
Sub OnceInSession()
Static blnAlreadyRun As Boolean

If blnAlreadyRun Then
Debug.Print "Already did..."
Exit Sub
Else
Debug.Print "Do something..."
blnAlreadyRun = True
End If
End Sub
Static변수는 런타임에러가 발생해도 값을 여전히 유지한다.
Sub OnceInSession()
Static blnAlreadyRun As Boolean

If blnAlreadyRun Then
Debug.Print "Already did..."
Exit Sub
Else
Debug.Print "Do something..."
blnAlreadyRun = True
On Error Resume Next
Err.Raise 1004

End If
End Sub
그러나 프로젝트가 종료되면 생명이 끝난다.
Sub OnceInSession()
Static blnAlreadyRun As Boolean

If blnAlreadyRun Then
Debug.Print "Already did..."
Exit Sub
Else
Debug.Print "Do something..."
blnAlreadyRun = True
End
End If
End Sub
위의 프로시저에서는 프로젝트를 종료하기 위해 End를 사용한다. 사실 VBA 프로젝트는 오류로 인해 원하지 않는 순간에 종료될 수 있다.

2)엑셀의 [이름]기능
엑셀의 [이름]에 값을 저장해두면 워크북 저장시 같이 저장되어 안정적으로 관리된다. 또 워크시트의 구석탱이 셀에 저장하는 것보다 덜 궁색하다.
Sub OnceWhenOpen()
Dim blnAlreadyRun As Boolean

blnAlreadyRun = Application.Evaluate("ONCE_WHEN_OPEN")

If blnAlreadyRun Then
Debug.Print "Already did..."
Exit Sub
Else
Debug.Print "Do something..."
blnAlreadyRun = True
ThisWorkbook.Names("ONCE_WHEN_OPEN").Value = blnAlreadyRun
End If
End Sub

(2)이항분포 실험기, 갤튼박스(Galton box) 또는 빈 머신(Bean Machine) 금융공학

지난 번에 쓴 포스트, (1)이항분포 실험기, 갤튼박스(Galton box) 또는 빈 머신(Bean Machine)에 이어 쓰는 두 번째 포스팅입니다. 학교에서 배운 정규분포는 종모양이고 무수히 많은 실험을 하게 되면 정규분포를 따른다고 한다. 하지만 기억나는 것은 종이위에 인쇄된 그저 종모양의 그래프이다. 실제 실험해볼 수 있다면 산 교육이 되겠지만 대학입학이라는 목표에 쫓기는 현실상 꽃놀이 같은 그런 실험은 엄두를 낼 수 없다.

이를 잘 알아 둔다면 금융공학에 필요한 확률분포함수를 배우는 셈이 된다. 이항분포실험기는 베르누이 시행을 배울 수 있는 좋은 도구이다. 베르누이 시행의 결과는 단 두 가지이다. 결과가 두 가지만 존재하는 대표적인 실험이 동전 던지기이다. 동전 던지기의 경우 앞면 또는 뒷면만 나오면 각각의 확률은 1/2이다.

앞면이 나올 사건 H가 나올 나올 확률이 p일 때, 앞면이 나오지 않을 사건 T가 나올 확률은 1-p이다. 이항분포 실험기처럼 베르누이 시행을 여러 번 시행해서 얻어진 확률분포를 이항분포라고 한다.

(시행을 거듭할 수록 구슬은 가운데로 모인다)


이항분포 실험기를 갖고 놀다보면 구슬은 가운데로 몰린다. 이제 그 이유를 알아보자. 갈림길이 4번 나오는 이항분포 실험기가 있다. 100개의 구슬을 넣는 시행을 하면 구슬은 왼쪽 또는 오른쪽으로만 이동할 수 있고 각각의 경우는 1/2의 확률을 가진다. 구슬이 이동할 수 있는 여러 가지의 경우중 가장 간단한 경우를 먼저 살펴보자.
(위의 그림은 갈림길이 6개인 경우지만)

시작점에서 구슬이 왼쪽으로만 4번 이동하여 1번 방에 들어가는 경우는 1가지이며 이동할 때마다 각각의 확률인 ½이 네 번 연속으로 나오는 것이므로그 확률은 ½*½*½*½이고 100번을 할 것이므로 100*½*½*½*½=6.25개이다.
2번 방의 경우 4개의 경우의 수가 나오며 100*((1/16)+(1/16)+(1/16)+(1/16)) = 25개이다.
3번 방의 경우 6개의 경우의 수가 나오며 100*((1/16)+(1/16)+(1/16)+(1/16)+(1/16)+(1/16)) = 37.5개이다.
4번 방과 2번 방과 같은 경우이도 5번 방의 경우는 1번 방과 마찬가지이므로 각각 25개, 6.25개이다.

이항분포 실험기를 파이썬으로 만들어 놓은 게 있다.
from collections import defaultdict
from math import sin, cos, radians as rads
from random import choice
from turtle import *

R = 5

def galton(nlevels=11, trace=False, speed=6):
setup(width=500, height=800, startx=0, starty=0)
delay(0)
pen(speed=10, shown=False)
goto(-200, -350)
clear()
goto( 200, -350)
pen(pendown=False)
# color('blue')
for n,y in enumerate(range(nlevels*14, -1, -14), 1):
for x in range(-7*n, 7*n+1, 14):
goto(x, y)
dot(6)
pen(speed=speed)
# color('red')
angles = (rads(d) for d in range(0,361,36))
addshape('marble', tuple((R*sin(r),R*cos(r)) for r in angles))
shape('marble')

hist = defaultdict(lambda:-343)
while True:
pen(shown=False, pendown=False)
x,y = 0, nlevels*14
goto(x, y)
pen(shown=True, pendown=trace)
delay(5)

while y > 0:
if y%14:
x += choice((-7,7))
goto(x, y)
y -= 7
goto(x, y)

delay(2)
while y > hist[x]:
y -= 7
goto(x, y)

stamp()
hist[x] += 7

if hist[x] > 0:
break

if __name__ == "__main__":
galton(4,False,1)


파이썬 따라하기 - 두 개의 배열을 합치기 EXCEL/VBA

두 개의 리스트를 원소별로 붙이는 파이썬 코드를 보니, VBA로 이건 안될 까 하는 생각이 들었다. 미리 결과를 말하자면 ['a1', 'b2', 'c3', 'd4', 'e5'] 이다.
x = ["a", "b", "c", "d", "e"]
y = [1, 2, 3, 4, 5]
z = map(lambda x,y:("%s%d" % (x,y)),x,y)
print(list(z))
그래서 두 가지를 해보았는데, (1)하나는 위의 파이썬 코드처럼 두 리스트의 원소끼리 맞붙여 보는 것이고, (2)나머지 하나는 그냥 기계적으로 직렬로 연결하는 것이다. (1)은 배열수식으로는 가능하지만 VBA구문상 어렵다. 그래서 엑셀의 힘을 빌려 보기로 했다.
    Dim arr1, arr2, arr3

arr1 = Array("a", "b", "c")
arr2 = Array("d", "e", "f")

On Error Resume Next
With ThisWorkbook
.Names("arr_1").Delete
.Names("arr_2").Delete
End With
On Error GoTo 0

With ThisWorkbook.Names
.Add "arr_1", arr1
.Add "arr_2", arr2
End With

arr3 = Application.Evaluate("=arr_1 & arr_2")
배열을 이름으로 지정하여 저장하고 , Evalueate()함수에 배열수식을 만들어 넣는 것이다.

(2)는 (1)보다 VBA로만 가능하여 훨씬 코드가 간략하다
    Dim arr1, arr2, arr3

arr1 = Array("a", "b", "c")
arr2 = Array("d", "e", "f")

arr3 = Split(Join(arr1, Chr(1)) & Chr(1) & Join(arr2, Chr(1)), Chr(1))
(2)은 두 개의 배열을 그냥 서로 이어 붙이는 것인데, Join()함수를 사용한다. Join()함수를 사용하여 배열의 각 원소를 하나의 문자열로 연결하고, 두 개의 배열과 Join(함수를 사용하여 얻은 두 개의 문자열을 다시 이어 붙인다. 그리고 Split()함수를 이용하여 다시 쪼개어 하나의 배열로 만드는 것이다.

Join() 과 Split() 함수 사용시 구분자를 흔히 사용하는 쉼표 등으로 하지 않은 것은, 배열내 원소중 그런 것들이 섞여 있어 잘못된 Split()결과가 나올 걸 대비해서이다. 가령 "a" 가 아니라 "a,"가 있는 데, 구분자를 쉼표(,)로 해버리면 Split() 결과, 빈 원소가 추가된 배열이 나올 수 있다. 그래서 키보드로 입력 가능하지 않은 문자중 아스키코드 1번 문자를 사용한 것이다.


[덧칠하기] 글을 쓰다보니 비슷한 포스팅을 한 적이 있다. [배열=배열+배열]에서 두 개의 1차원 배열을 합쳐 하나의 배열 2차원 배열을 만들었는데, 이번의 것은 1차원 배열의 원소를 합쳐 1차원 배열을 만드는 것이다.

그리고 (2)의 방법도 그 포스팅에서 다루었다. 그 당시(2017.12.07)에는 쉼표(,)를 구분자로 사용하였다. 그 포스팅을 전혀 기억하지 못하고 쓴 글인데, 비슷한 글을 또 쓰고 있다. 대단한 우연이다.


오랜만에 풀어 보는 SQL 문제 Data science

얼마 전 친한 형님이 급히 풀어달라는 과제가 있었는데, 그중에 SQL을 만드는 것이 있었다. https://github.com/rushpartners/data-analyst-challenge/tree/master/part-2
You have been asked to get some answers from a database on a set of data. The database contains an archive of bids made by users for players over the years. The database contains years of data and you will need to write raw SQL queries to answer the questions.

Using the table structure below, provide the SQL queries required to answer as many of the following questions:
1) What is the total number of users who have placed a bid on Wayne Rooney whilst playing for Manchester United?
2) What is the total number of bids for Cristiano Ronaldo placed by users in Spain?
3) What is the total number of users who have never placed a bid?
4) What is the % of bids for each player
5) What is the % of bids for each team
6) Rank teams in order of the # of bids their players have had.

(테이블#1) [Users] - (컬럼) id, username, country
(테이블#2) [Bids] -(컬럼) id, user_id, player_id, value, date
(테이블#3) [Players] - (컬럼) id, name, team


그리 어려운 것은 아닌데, 그중 하나는 인상이 깊었다. 3)문제인데, bid를 하지 않는 사용자의 숫자를 구하는 것인데, 평소에 조건에 해당하는 쿼리를 했는데, 이번에는 조건에 해당하지 않는(NEVER) 사용자 수를 구하는 것이다.
간단히 전체 사용자 숫자에서 비딩에 참여한 사용자숫자를 빼면 된다. 그래서
SELECT COUNT(a.id) - COUNT(DISTINCT b.user_id) FROM Users a, Bids b


그런데 다른 방법(고수처럼 보이는)이 있을 것 같아 자주 가는 포럼에 도움을 구했더니, 다음과 같은 답을 얻었다. 멋진 쿼리이다.
SELECT COUNT(*) FROM Users WHERE users_id NOT IN ( SELECT users_id FROM Bids )



간단한 초보적 질문에 어렵게 답하기 EXCEL/VBA

다 아는 사실이지만 많이 아는 것과 잘 가르치는 것은 별개이다. 눈 높이에 마추어 가르치고 답을 주는 것이 좋은 것이 아닐까? 그러나 뭔가 고수같은 품격을 살리기 위해 일부러 어렵게 답하는 만행을 상대방 앞에선 하지 못하고 이렇게 블로그에 옮겨 본다.

하나의 시트속의 숫자들을 다른 시트로 복사하는 데, 그냥 복사가 아니라 1000으로 나눈 결과를 붙여 넣는 것이다. 손으로 한다면 누구라도 하는 간단한 것이지만, VBA 초보의입장에선 첫 걸음 떼는 아기처럼 어려운 일이다.




FM(교본)같은 답변은 이럴 것이다.
Dim rng As Range  

Worksheets("Sheet1").Range("A2:A7").Copy Worksheets("Sheet2").Range("A2")

For Each rng In Worksheets("Sheet2").Range("A2:A7")

rng.Value = rng.Value / 1000

Next
그러나 코딩골프 놀이를 하고 싶어 코드를 더 줄이기 위해 이전에 내 블로그를 참조(원래 블로깅하는 목적이기도 하다)하여 만든 쓸데없는 잉여짓은 다음과 같다.

1) Sheet2.Range("A2:A7").FormulaArray = "=Sheet1!A2:A7/1000"
위의 방법은 배열수식을 입력하는 방법이다. 수식이 들어가다 보니, 수식/함수가 많다면 연산에 부담이 될 것이다.

2) Sheet2.Range("A2:A7") = Sheet1.Evaluate("Sheet1!A2:A7/1000")
위의 방법은 예전에 포스팅한 Evaluate()메서드를 이용한 것이다. 수식의 결과는 값으로 떨어지고, 속도도 빨라서 만족스럽다. 그러나 "..." 같은 문자열안에 수식을 하드 코딩해 둔 것이라, 셀 주소를 변수로 처리하는 게 실용적이다.

3) 앞의 2)의 하드코딩을 고쳐 쓰자면,
Dim rng As Range

Set rng = Sheet1.Range("A2:A7")

Sheet2.Range("A2:A7") = Sheet1.Evaluate(rng.Address & "/1000")


표준편차를 이용한 등수 구하기 Data science

학생시절에 시험을 치루고 난 뒤 하는 일은 점수를 맞춰 보는 것이다. 기억에 나는 문제를 얘기하며 "그 문제 정답이 뭐냐?" 부터 시작하여 그 과목의 점수가 얼마 나오겠구나 하는 예상을 해보곤 한다. 사실 그거 할 시간에 다음 시험과목 준비를 하는 것이 나을 것이다.
막간을 이용하여 통계학 책에 나온 예제를 VBA로 만들어 보았다. 가령 학교에서 시험을 보고 등수를 추정하고 동점자수를 예상해보는 것이다. 사실 등수를 추정하는 것은 내 점수의 백분위수를 알고 전체 학생수를 안다면 어려운 일은 아니다. 둘이 곱하면 되는 것이므로... 동점자 수를 추정하는 것도 내 점수 인원수에서 내 점수보다 1점 높은 친구들의 숫자를 빼는 것이다.
Sub Get_Rank_Using_Standard_Deviation()
Dim num As Long
Dim score As Long
Dim mean As Double
Dim stdev As Double

Dim pencentile As Double
Dim estimated_rank As Long
Dim estimated_num_of_peer As Long

num = 130
score = 70
mean = 71.6
stdev = 17.1

With WorksheetFunction
pencentile = 1 - .Norm_Dist(score, mean, stdev, 1)
estimated_rank = pencentile * num
estimated_num_of_peer = estimated_rank _
- (1 - .Norm_Dist(score + 1, mean, stdev, 1)) * num
End With

Debug.Print
Debug.Print "<<표준편차를 이용한 등수 구하기>>"
Debug.Print "1. 백분위:"; Format(pencentile, "0.00%")
Debug.Print "2. 추정등수:"; estimated_rank
Debug.Print "3.추정동점자수:"; estimated_num_of_peer
End Sub


증권사 API를 사용하면서 느끼는 여러 생각 증권

대신증권의 사이보스 초기시절부터 증권사API를 이용한 시스템 트레이딩 또는 자동매매 시스템을 만들겠다는 생각만 가지고 있었다. 비교적 최근에는 미국에서 유행한 알고리즘 트레이딩 붐에 힘입어 이베스트증권의 Xing API라던가 키움증권의 OpenAPI가 대중에 인기를 끌고 있다. 두 회사의 API를 만지작 거려 보았지만, 딱히 목적이 없어 본격적인 작업을 해보진 않았다. 그러나 API 문서화, 모의 시스템 지원, 참고자료, 회사의 공개강의 등 두 회사의 API는 가장 대중적이고 인기있다.

회사 일로서 대우증권의 API를 이용하여 선물매매시스템을 만들고 운용한 경험도 있는데, 이번에는 신한증권의 API를 이용한 시스템을 만들고 있다. 신한증권을 선택한 이유는 매매하고 싶은 미국선물(VIX선물때문이다. 그러나 VIX옵션이 없어 아쉽지만) 때문이다. 다행히 신한증권은 해외선물 예제를 엑셀로 제공하고 있어, API를 학습하는 면에선 큰 어려움이 없다.

다만 최근에 엑셀로 파일럿 프로그램을 만들면서 애로사항이 하나 생겼다. 한번에 세 개의 종목 시세를 받기가 힘들다는 점이다. 간혹 세 개의 시세를 받는 데 성공하기도 하지만 말이다. 여러 번 시도를 하면 성공한다. 다만 1번에 성공하지 못하는 것일 뿐. 조회TR을 요청하면 에러없이 조회ID를 얻기는 하지만 꼭 한 종목의 콜백함수가 호출이 안되고 있다.

물론 이건 API문제는 아니고 엑셀의 문제이다. C#으로 작성한 프로그램은 잘 작동하는 걸 보면 그런 생각이 든다. 사실 엑셀이 이런 용도로 만들어진 프로그램이 아니다. 그러나 본격적인 프로그램을 만들기에 앞서 화면구성이나 API학습, 각종 테스트를 위해 엑셀로 파일럿(Pilot)을 만드는 작업이 마냥 시간낭비는 아니다. 전체적인 개발 프로세스를 줄이는 방법이라고 생각한다.

RANK()함수를 VBA에서 사용하려고 보니... EXCEL/VBA

VBA를 강의하거나 관련 글을 쓰면서 자랑스럽게 VBA의 강점으로 소개하는 것이 WorksheetFunction 개체이다. WorksheetFunction은 엑셀의 워크시트함수를 VBA에서 사용할 수 있도록 해주는 고마운 개체이다. 이 덕분에 VLOOKUP() 함수와 같은 기능을 직접 만들 필요가 없다. 오히려 내가 만든 함수보다 더 빠르고 신뢰성이 높다.

그러나 이번에 RANK()함수를 처음 사용하면서 난감하게 되었다. RANK()함수는 일련의 값의 배열에서 특정 값의 순위를 돌려준다. 그러나 RANK()함수에 전달하는 매개변수중 ref 매개변수에 Range개체가 아닌 Variant배열, 수치형 데이터 배열을 주게 되면 오류(컴파일에러와 런타임에러(424))가 난다(다른 워크시트함수에서는 배열을 던져 놓은 것이 가능했는데...)
'// Variant변수를 사용하는 경우 424 런타임 에러 - 개체가 필요합니다
Debug.Print .rank(rng.Value, arrVar, RankOrder.Ascending)

'// 수치형 데이터배열을 사용하는 경우 컴파일 에러 - 형식이 일치하지 않습니다
Debug.Print .rank(rng.Value, arrLng, RankOrder.Ascending)


계산중간에 생기는 값들이라 RANK()함수를 사용하려고 이들를 워크시트에 저장하고 다시 읽는 것은 삽질오브삽질일 것이다. 안정적인 장시간의 실행이 필요한터라 워크시트 입출력을 되도록 줄이고 대부분의 데이터처리를 메모리속에서 실행되도록 만드는 중이다. 그래서 RANK함수와 타협을 할 여지가 없다. 그래서 따로 함수를 만들었다. 굳이 정성을 들일 부분이 아니라서 간단히 LARGE()/SMALL()함수를 이용하였다.
Enum RankOrder
Descending
Ascending
End Enum

Function GetRank(item, itemArray, Order As RankOrder) As Long
Dim i As Long
Dim rnk As Long

If Order = RankOrder.Ascending Then
'// 오름차순
rnk = 1
For i = LBound(itemArray) To UBound(itemArray)
If item = WorksheetFunction.Small(itemArray, )rnk Then
GetRank = rnk
Exit For
End If
rnk = rnk + 1
Next
Else
'// 내림차순
rnk = 1
For i = LBound(itemArray) To UBound(itemArray)
If item = WorksheetFunction.Large(itemArray, rnk) Then
GetRank = rnk
Exit For
End If
rnk = rnk + 1
Next
End If
End Function

따지고 보면 RANK함수와 LARGE()/SMALL()함수는 서로 관계가 있다. RANK함수의 리턴 값은 LARGE()/SMALL()함수의 매개변수가 되며, LARGE()/SMALL()함수의 리턴값은 RANK함수의 매개변수가 될 수 있다.
다음은 사용 예이다.
Sub demoRank()
Dim s As Worksheet, rng As Range
Dim xlrank As Long, myrank As Long
Dim i As Long

Set s = Sheet1

With WorksheetFunction
Dim arrVar

arrVar = .Transpose(s.Range("A1:A20").Value)

Dim arrLng(1 To 20) As Long

i = 1
For Each rng In s.Range("A1:A20")
arrLng(i) = rng.Value
i = i + 1
Next

For Each rng In s.Range("A1:A20")
'// Variant변수를 사용하는 경우 424 런타임 에러 - 개체가 필요합니다
'Debug.Print .rank(rng.Value, arrVar, RankOrder.Ascending)

'// 수치형 데이터배열을 사용하는 경우 컴파일 에러 - 형식이 일치하지 않습니다
'Debug.Print .rank(rng.Value, arrLng, RankOrder.Ascending)

'// 에러가 없지만 Range개체를 사용해야 한다
xlrank = .rank(rng.Value, s.Range("A1:A20"), RankOrder.Ascending)

'// arrVar변수를 사용한다.
myrank = GetRank(rng.Value, arrVar, RankOrder.Ascending)
Debug.Print rng.Value; xlrank; myrank
Next
End With
End Sub

루프를 사용하지 않고 배열을 워크시트에 한번에 출력하는 방법이... EXCEL/VBA

최근 블로깅이 뜸하였는 데, 먹고 사는 일에 바쁘다 보니 블로깅하는 호사를 부릴 수 없었다. 알고트레이딩 프로그램을 작성중인데, 프로토(proto) 타입 삼아 엑셀로 만드는 중이다. 아마도 시세와 이에 반응하는 알고리즘 분석/리뷰용이나 비상시 임시방편 트레이딩으로는 가능할 것이다. 엑셀이 알고트레이딩용 언어는 아니라서 몇 가지 한계를 접하는 중이다(실시간 시세를 받아오는 콜백함수의 피로누적으로 인한 런타임 오류, 저장시 메모리 부족 등등)

그래서 불필요한 워크시트 입출력을 줄이고 메모리상에서 데이터를 처리하는 코드로 바꾸어 놓았지만, 최종의 결과는 워크시트에 출력하는 것이 여러모로 편리하다. 오늘은 배열에 저장해둔 내용을 루프를 사용하지 않고 워크시트로 출력하는 방법이
없을 까 하는 궁리를 해보았다

다음은 테스트 삼아 단순한 1차원 배열을 워크시트에 출력하는 예이다. Transpose()함수를 사용하여 차원을 돌려 출력하는 것이 요령이다.
    Dim arr(5) As String

arr(0) = "Hello"
arr(1) = "World"
arr(2) = "Cancel"
arr(3) = "Absolutely"
arr(4) = "Corporate"
arr(5) = "Duty"

With Sheet1.Range("A1:A6")
.ClearContents
.value = WorksheetFunction.Transpose(arr)
End With
1차원이 아니라 2차원이라면 Tanspose없이 그대로 하면 된다.
    Dim arr(5, 2) As String

arr(0, 0) = "Hello": arr(0, 1) = "Hello": arr(0, 2) = "Hello"
arr(1, 0) = "World": arr(1, 1) = "World": arr(1, 2) = "World"
arr(2, 0) = "Cancel": arr(2, 1) = "Cancel": arr(2, 2) = "Cancel"
arr(3, 0) = "Absolutely": arr(3, 1) = "Absolutely": arr(3, 2) = "Absolutely"
arr(4, 0) = "Corporate": arr(4, 1) = "Corporate": arr(4, 2) = "Corporate"
arr(5, 0) = "Duty": arr(5, 1) = "Duty": arr(5, 2) = "Duty"

With Sheet1.Range("A1:C6")
.ClearContents
.value = arr
End With
그러나 단순한 배열이 아니라 사용자 정의 타입 배열을 처리하는 게 관심사이다.
Public Type udt
tag As String
dte As Date
value As Double
End Type

Sub demoArray2()
Dim arr(5) As udt

arr(0).tag = "Hello": arr(0).dte = #10/27/1979#: arr(0).value = 123
arr(1).tag = "World": arr(1).dte = #9/11/1968#: arr(1).value = 23
arr(2).tag = "Good": arr(2).dte = #3/8/2018#: arr(2).value = 142
arr(3).tag = "Morning": arr(3).dte = #1/27/1981#: arr(3).value = 612
arr(4).tag = "Best": arr(4).dte = #10/21/1974#: arr(4).value = 723
arr(5).tag = "Wish": arr(5).dte = #12/31/2005#: arr(5).value = 456

Sheet1.Range("B1:D6") = Application.Transpose(arr()) '// 에러 작렬
End Sub
오류가 났는데, 각 단어는 알겠는데, 합쳐 놓으니 무슨 소리인지 모르겠다 . 또 다른 삽질의 시작~


오랜만에 데이터베이스 프로그래밍을 해볼려고 하는데... 삽질


"왕년에는 이 정도쯤은 문제도 아니었는데..."


오랜만에 데이터베이스 프로그래밍을 해볼려고 했는데, 우와 왕창 까먹은 자신을 보니 영화 "신라의 달밤"의 한 장면이 떠오른다. 한 때 고등학교에서 짱 먹었던 왕년의 주먹은 사라지고 일개 고등학교 체육교사가 된 차승원이 김혜수를 사이에 두고 모범생에서 조폭의 작은 두목이 된 이성재와의 대결을 위해 학교 운동장에서 체력단력을 하던 장면이 머리속에 떠오른다.

진짜 옛날엔 이 정도는 껌이었는데, 이제 다 까먹었다. 옛날에 만든 프로젝트를 뒤져봐야 겠다. 디비커넥션, 레코드셋, 커밋/롤백, 스토어드프로시저, 각종 쿼리 얘네들 다시 찾아와야 겠다.


해석적(Analytical)이라는 표현 금융공학

책을 읽다 보면 어떤 함수가
해석적(Analytical)
이라는 표현을 보는 수가 있다. 한국어인데 이해가 쉽게 안된다. 이는
이미 우리가 알고 있는 함수들의 조합으로 그 함수를 표현할 수 있다
것을 의미한다.

맞는 비유인지는 모르겠지만 곱셈을 함수로 본다면 덧셈이라는 함수를 가지고 곱셈을 표현할 수 있고, 또한 나눗셈은 뺄셈으로 표현할 수 있다.



하이투자증권 도서관 증권

오랜만에 방치하던 증권계좌를 스마트폰앱으로 찾아 보았다. 이러 저런 기능을 살펴보다가 스마트하이플러스 전자도서관이라는 게 있다. 예스24와 연계된 서비스인듯 하다. 오호~ 이거 좋은 기능이네...


그러나 막상 해볼려고 했더니... 잔고가 달랑 10만원이라...



돈 생기면 300만원 넣어봐야 겠다

껌 하나 안사먹었으면 300만원 넣어 두었을 텐데, 아쉽네요. 낼부터 적금 하나 만들어 봐야겠어요.



Uninstalling Anaconda PYTHON

Uninstalling Anaconda

To uninstall Anaconda, you can do a simple remove of the program. This will leave a few files behind, which for most users is just fine. See Option A.

If you also want to remove all traces of the configuration files and directories from Anaconda and its programs, you can download and use the Anaconda-Clean program first, then do a simple remove. See Option B.

Option A.

Use simple remove to uninstall Anaconda:

macOS–Open the Terminal.app or iTerm2 terminal application, and then remove your entire Anaconda directory, which has a name such as anaconda2 or anaconda3, by entering rm -rf ~/anaconda3
.

Option B.

Full uninstall using Anaconda-Clean and simple remove.

NOTE: Anaconda-Clean must be run before simple remove.

Install the Anaconda-Clean package from Anaconda Prompt or a terminal window:

conda install anaconda-clean

In the same window, run one of these commands:

Remove all Anaconda-related files and directories with a confirmation prompt before deleting each one:

anaconda-clean

Or, remove all Anaconda-related files and directories without being prompted to delete each one:

anaconda-clean --yes

Anaconda-Clean creates a backup of all files and directories that might be removed, such as .bash_profile
, in a folder named .anaconda_backup
 in your home directory. Also note that Anaconda-Clean leaves your data files in the AnacondaProjects directory untouched. After using Anaconda-Clean, follow the instructions above in Option A to uninstall Anaconda. Removing Anaconda path from .bash_profile

If you use Linux or macOS, you may also wish to check the .bash_profile
file in your home directory for a line such as:

export PATH="/Users/jsmith/anaconda3/bin:$PATH"

NOTE: Replace /Users/jsmith/anaconda3/
 with your actual path.

This line adds the Anaconda path to the PATH environment variable. It may refer to either Anaconda or Miniconda. After uninstalling Anaconda, you may delete this line and save the file.



일상불만족-확률변수, 확률과정 금융공학

유리수, 무리수 같은 용어가 마음에 들지 않는 이유는 한번에 그 의미를 이해하기 어렵다는 것이다. 물론 어려운 개념을 한자어로 옮겨 놓은 것이라(혹시 일본식 용어일지도) 중고등학생부터 그 중고등학생이 성장해 성인이 되어서도 선뜻 이해가 안되는 것이다.

확률변수, 확률과정도 유리수, 무리수 같은 넘들이다. 확률변수라는 넘은 확률+변수라는 단어의 조합인데, 둘 다 쉬운 말은 아니다. 실상 확률변수는 변수라고 하지만 함수이기도 하다. 함수라는 것은 무언가를 돌려주는 것이다.

주사위를 가지고 확률변수를 설명하자면, 주사위의 눈은 1~6사이의 값이다. 확률변수는 1~6사이에서 임의로(같은 확률이지만) 결정되는 결과 값으로 본다. 한편 주사위를 던지는 과정을 상상해보자. 주사위를 던지면 주사위는 내 손을 떠나 공중에서 찰나의 순간동안 머물게 된다. 그리고 땅에 떨어져 구르다가 멈추면서 1~6 사이의 값중 하나를 보여준다. 주사위가 손을 떠나 공중에 머물다 추락하면서 지면에서 굴러 결과값을 보여주는 일련의 과정은 함수이다. 내 손을 떠난 이후 무슨 일이 일어났는 지는 모르지만 결과값을 보여주기 때문이다.

확률변수라는 것을 흔하게 볼 수 있는 장면이 정규분포 그래프이다. x축은 확률변수의 땅이다. 표준정규 누적분포함수(Cumulative Normal Standard Distribution)의 확률변수는 음의 무한대에서 양의 무한대이다. 한 쪽에는 깊은 바다와 반대 편에는 높은 산이 있는 있는 셈이다.

확률과정이라는 말도 한번 따져보자. 확률은 이미 아는 개념이니까 넘어가고 과정이라는 말이 거시기하다. 확률이 무슨 과정을 겪는 건가? 용어가 어렵다보니 엉뚱한 상상을 하게 된다. 동전 던지기 실험을 10분마다 한번씩 시행하기로 했다고 하자. 10분마다 그 결과값이 생기면서 결과(확률변수)가 모아지는 데, 이렇게 결과 값을 모은 것을 확률과정이라고 할 수 있다. 확률변수의 집합=확률과정 이다. 환율, 주가, 금리 등의 변화가 확률과정이다.


Risk-Return Ratio 증권

Risk-Return Ratio(RRR)는 일정기간동안의 위험관점에서 본 일종의 위험조정수익률이다. 이때 위험은 MDD(Maximum Drawdown)을 사용한다.
RRR=R/MDD

여기서 R=(Pend-Pstart)/Pstart, Pend는 기간말 가격, Pstart는 기간초 가격이다.



TA-Lib 파이썬 패키지 설치 삽질기 PYTHON

학술적으로 기술적 분석은 미신이나 다름 없다. 그러나 과거의 데이터를 갖고 미래를 예측해보려는 인간의 공통적인 행위중 하나이고, 어떤 패턴을 파악해서 불안한 미래를 예측하여 마음의 안정을 갖으려는 원초적인 노력의 결과이기도 하다.

예전에 기계적으로 계산 가능한 기술적 지표를 엑셀과 VBA로 만들어 보려는 노력을 하던 때가 있었는데, 그 당시 알게 된 것이 TA-Lib이다. 그냥 흔한 C언어용 라이브러리인줄 알았는데, 기술적 분석과 관련하여 기억나는 라이브러리는 TA-Lib뿐이다.
    알고리즘 트레이딩 자료를 만들기 위해 zipline 관련 문서를 정리하고 있는 데, 개발환경구축이 사실 막장 느낌이다.
  1. zipline은 플랫폼에선 자유로운 반면 파이썬3.5버전까지만 지원한다.
  2. 아나콘다 최신버전은 파이썬3.6이다
  3. 아나콘다 아카이브에서 4.2.0버전을 다운 받거나 conda명령으로 파이썬3.5 설치
  4. 국내 증권사 API가 윈도우 플랫폼만 지원하며, 파이썬32비트 버전을 사용해야 한다(이 부분은 확인 필요)
  5. TA-Lib는 필수는 아니지만 이거 없으면 매매알고리즘을 만들 때 엄청 피곤할 것이다.
  6. TA-Lib버전은 윈도우 플랫폼이 가능하지만 소스코드를 컴파일해야 한다(그래서 VC++ Build Tools 또는 VS 필요)
  7. TA-Lib64비트 버전은 공식적으로 지원없음(소스를 컴파일하는 방법 가능)
  8. 게다가 zipline이 32비트 지원을 중단하는 일은 시간의 문제
결론은 #윈도우 #32비트 파이썬 #3.5.이하 파이썬 #불편한 TA-Lib설치이다

ta-lib란?
주식 차트의 기술적 분석을 위한 200여 가지의 지표 함수를 제공하는 C 라이브러리인데, 파이썬으로 포팅되어있다.
- 공식홈페이지: http://ta-lib.org/
- 함수 목록: http://ta-lib.org/function.html
- Python 패키지 및 엑셀 플러그 인 제공
https://github.com/mrjbq7/ta-lib
http://mrjbq7.github.io/ta-lib/doc_index.html

설치로그:나의 오후를 잡아 먹은 삽질을 정리해보았다.
앞서 아나콘다4.2.0(파이썬3.5) 32비트 버전과 zipline이 설치된 상태에서
    # 소스코드 컴파일하여 설치하는 방법(Install TA-Lib C Library on Windows 10)
  1. Download and Unzip ta-lib-0.4.0-msvc.zip(https://github.com/mrjbq7/ta-lib)
  2. Move the Unzipped Folder ta-lib to C:\
  3. Download and Install Visual Studio Community 2015 또는 Visual C++ Build Tools
  4. Build TA-Lib Library
    4-1) 명령프롬프트 실행 [VS2015 x86 Native Tools Command Prompt]
    4-2) C:\ta-lib\c\make\cdr\win32\msvc 로 이동
    4-3) nmake 실행
  5. [Anaconda Prompt] 실행(관리자권한으로 실행 추천)
  6. pip install ta-lib
  7. 임포트시 RuntimeError: module compiled against API version 0xb but this version of numpy is 0xa 같은 에러가 나는 경우 numpy업그레이드(pip install numpy --upgrade)
    # 비공식 윈도우용 바이너리로 설치하는 방법(Unofficial Windows Binaries for Python Extension Packages)
  1. https://www.lfd.uci.edu/~gohlke/pythonlibs/#ta-lib 로 이동
  2. TA_Lib‑0.4.16‑cp35‑cp35m‑win32.whl 을 다운받는다(32비트 파이썬3.5용 TA-Lib)
  3. [Anaconda Prompt] 실행
  4. pip install TA_Lib‑0.4.16‑cp35‑cp35m‑win32.whl


세상에서 가장 쉬운 베이즈 통계학 입문

지난 연말부터 이번 달 중순까지 책을 한 권 읽고 나름대로 정리하는 시간을 가져 보았다. 한 권을 읽고 정리하고 보니 뿌듯한 느낌이 들었다. 그래서 결심한 것이 2018년 올 한해에는 책을 대충 읽지 말고 끝까지 읽고 정리를 해볼까 한다. 그래서 읽고 정리한 책이 "세상에서 가장 쉬운 베이즈 통계학 입문"이다. 통계학도 잘 모르는 상황에서 베이즈 통계학을 공부하겠다고 몇 권의 책을 보고 좌절했다. 어찌 초반에만 쉬운 지...뒤로 갈 수록 @.@

결론부터 말하자면 베이즈 통계학을 처음 입문하고자 하는 분은 꼭 한번 읽어보시길 바이다. 소개한 바와 같이 책은 복잡한 수식없이 단순 계산만 갖고 진행한다. 그리고 이 책의 장점중 하나는 확률의 개념을 면적으로 보고 조건부 확률과 관측 정보를 곱하는 방식으로 확률을 설명하고 있다. 책은 1부와 2부로 나눠져 있는데, 1부는 재미있는 산수공부처럼 생각하고 읽어 나갈 수 있다. 그러나 2부는 약간 미간을 구겨가며 집중을 하면서 읽어야 한다 (책의 중간 중간에 오타/오류가 있는 데, 번역출판과정에서 생긴 듯하다)

저자는 일본 데이쿄 대학교 경제학부에 재직중인 고지마 히로유키교수이다. 사실 이 분의 책을 한 권 더 가지고 있었다. "세상에서 가장 쉬운 통계학 입문"이 그것인데, 공교롭게도 책을 사다보니 같은 저자였다. 이 책은 통계지식이 그냥 부족한 게 아니라 절대 부족한 사람들을 위해 쓴 책인데, 이 책을 먼저 읽어도 된다.

윈도에서 PyMC3 설치 PYTHON

지난 번에 우분투에서 PyMC를 설치하는 걸 포스팅한 적이 있는 데, 우분투나 맥이야 컴파일러가 아예 포함되어 있는 등 개발이 편한 점이 있지만 윈도우는 그렇치 않아 PyMC3 설치가 까다로운 듯하다. 처음에 파이썬3.6하에서 PyMC3를 설치하였는데, 거기에 필요한 theano가 파이썬 3.6을 아직 지원하지 않아 결국은 실패.

그래서 재수하여 파이썬3.5 가상개발환경을 만들고 PyMC3를 설치하여 보았다. 결론은 주관적으로 80~90% 성공(아직 샘플을 하나만 돌려서 나중에 뭔 에러가 날지는 모르겠지만) 다음은 설치한 내역인데, 참고 삼아 올려본다.

정리하면 :
1. conda create -n bayes python=3.5.3 anaconda
2. activate bayes
3. conda install -c conda-forge pymc3
4. conda install numpy scipy mkl-service libpython m2w64-toolchain

Welcome to Anaconda

(C:\Users\JIMSJOO\Anaconda3) C:\Users\JIMSJOO>conda create -n bayes python=3.5.3 anaconda
Fetching package metadata .............
Solving package specifications: .

Package plan for installation in environment C:\Users\JIMSJOO\Anaconda3\envs\bayes:

The following NEW packages will be INSTALLED:

anaconda: custom-py35h64770cb_0
certifi: 2017.11.5-py35h456c6ae_0
pip: 9.0.1-py35h691316f_4
python: 3.5.3-3
setuptools: 36.5.0-py35h21a22e4_0
vc: 14-h2379b0c_2
vs2015_runtime: 14.0.25123-hd4c4e62_2
wheel: 0.30.0-py35h38a90bc_1
wincertstore: 0.2-py35hfebbdb8_0

Proceed ([y]/n)? y

#
# To activate this environment, use:
# > activate bayes
#
# To deactivate an active environment, use:
# > deactivate
#
# * for power-users using bash, you must source
#


(C:\Users\JIMSJOO\Anaconda3) C:\Users\JIMSJOO>activate bayes
Welcome to Anaconda

(bayes) C:\Users\JIMSJOO>conda install -c conda-forge pymc3
Fetching package metadata ...............
Solving package specifications: .

Package plan for installation in environment C:\Users\JIMSJOO\Anaconda3\envs\bayes:

The following NEW packages will be INSTALLED:

backports: 1.0-py35_1 conda-forge
backports.functools_lru_cache: 1.4-py35_1 conda-forge
ca-certificates: 2017.11.5-0 conda-forge
cycler: 0.10.0-py35_0 conda-forge
freetype: 2.8.1-vc14_0 conda-forge [vc14]
h5py: 2.7.1-py35_2 conda-forge
hdf5: 1.10.1-vc14_1 conda-forge [vc14]
icc_rt: 2017.0.4-h97af966_0
icu: 58.2-vc14_0 conda-forge [vc14]
intel-openmp: 2018.0.0-hd92c6cd_8
joblib: 0.11-py35_0 conda-forge
jpeg: 9b-vc14_2 conda-forge [vc14]
libgpuarray: 0.7.5-vc14_0 conda-forge [vc14]
libpng: 1.6.34-vc14_0 conda-forge [vc14]
mako: 1.0.7-py35_0 conda-forge
markupsafe: 1.0-py35_0 conda-forge
matplotlib: 2.1.1-py35_2 conda-forge
mkl: 2018.0.1-h2108138_4
numpy: 1.14.0-py35h4a99626_0
openssl: 1.0.2n-vc14_0 conda-forge [vc14]
pandas: 0.22.0-py35_0 conda-forge
patsy: 0.5.0-py35_0 conda-forge
pygpu: 0.7.5-py35_0 conda-forge
pymc3: 3.2-py35_0 conda-forge
pyparsing: 2.2.0-py35_0 conda-forge
pyqt: 5.6.0-py35_4 conda-forge
python-dateutil: 2.6.1-py35_0 conda-forge
pytz: 2017.3-py_2 conda-forge
qt: 5.6.2-vc14_1 conda-forge [vc14]
scipy: 1.0.0-py35h75710e8_0
sip: 4.18-py35_1 conda-forge
six: 1.11.0-py35_1 conda-forge
theano: 1.0.1-py35_1 conda-forge
tornado: 4.5.3-py35_0 conda-forge
tqdm: 4.19.5-py_0 conda-forge
zlib: 1.2.11-vc14_0 conda-forge [vc14]

Proceed ([y]/n)? y

ca-certificate 100% |###############################| Time: 0:00:02 76.97 kB/s
backports-1.0- 100% |###############################| Time: 0:00:00 293.55 kB/s
joblib-0.11-py 100% |###############################| Time: 0:00:01 115.96 kB/s
markupsafe-1.0 100% |###############################| Time: 0:00:00 109.96 kB/s
numpy-1.14.0-p 100% |###############################| Time: 0:00:00 8.68 MB/s
pyparsing-2.2. 100% |###############################| Time: 0:00:00 100.65 kB/s
pytz-2017.3-py 100% |###############################| Time: 0:00:01 111.23 kB/s
sip-4.18-py35_ 100% |###############################| Time: 0:00:02 242.40 kB/s
six-1.11.0-py3 100% |###############################| Time: 0:00:00 1.39 MB/s
tornado-4.5.3- 100% |###############################| Time: 0:00:02 234.72 kB/s
cycler-0.10.0- 100% |###############################| Time: 0:00:00 0.00 B/s
h5py-2.7.1-py3 100% |###############################| Time: 0:00:03 210.72 kB/s
mako-1.0.7-py3 100% |###############################| Time: 0:00:00 186.76 kB/s
pyqt-5.6.0-py3 100% |###############################| Time: 0:00:05 875.71 kB/s
python-dateuti 100% |###############################| Time: 0:00:03 76.87 kB/s
backports.func 100% |###############################| Time: 0:00:00 612.81 kB/s
pandas-0.22.0- 100% |###############################| Time: 0:00:08 1.17 MB/s
patsy-0.5.0-py 100% |###############################| Time: 0:00:03 88.86 kB/s
pygpu-0.7.5-py 100% |###############################| Time: 0:00:02 260.30 kB/s
matplotlib-2.1 100% |###############################| Time: 0:00:06 1.13 MB/s
theano-1.0.1-p 100% |###############################| Time: 0:00:06 622.71 kB/s
pymc3-3.2-py35 100% |###############################| Time: 0:00:04 275.41 kB/s

(bayes) C:\Users\JIMSJOO>python
Python 3.5.3 |Anaconda custom (64-bit)| (default, May 15 2017, 10:43:23) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import pymc3 as pm
WARNING (theano.configdefaults): g++ not available, if using conda: `conda install m2w64-toolchain`
C:\Users\JIMSJOO\Anaconda3\envs\bayes\lib\site-packages\theano\configdefaults.py:560: UserWarning: DeprecationWarning: there is no c++ compiler.This is deprecated and with Theano 0.11 a c++ compiler will be mandatory
warnings.warn("DeprecationWarning: there is no c++ compiler."
WARNING (theano.configdefaults): g++ not detected ! Theano will be unable to execute optimized C-implementations (for both CPU and GPU) and will default to Python implementations. Performance will be severely degraded. To remove this warning, set Theano flags cxx to an empty string.
WARNING (theano.configdefaults): install mkl with `conda install mkl-service`: No module named 'mkl'
WARNING (theano.tensor.blas): Using NumPy C-API based implementation for BLAS functions.

C:\Users\JIMSJOO\Anaconda3\envs\bayes\lib\site-packages\h5py\__init__.py:36: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.
from ._conv import register_converters as _register_converters
>>> exit()

(bayes) C:\Users\JIMSJOO>conda install numpy scipy mkl-service libpython m2w64-toolchain
Fetching package metadata .............
Solving package specifications: .

Package plan for installation in environment C:\Users\JIMSJOO\Anaconda3\envs\bayes:

The following NEW packages will be INSTALLED:

libpython: 2.1-py35_0
m2w64-binutils: 2.25.1-5
m2w64-bzip2: 1.0.6-6
m2w64-crt-git: 5.0.0.4636.2595836-2
m2w64-gcc: 5.3.0-6
m2w64-gcc-ada: 5.3.0-6
m2w64-gcc-fortran: 5.3.0-6
m2w64-gcc-libgfortran: 5.3.0-6
m2w64-gcc-libs: 5.3.0-7
m2w64-gcc-libs-core: 5.3.0-7
m2w64-gcc-objc: 5.3.0-6
m2w64-gmp: 6.1.0-2
m2w64-headers-git: 5.0.0.4636.c0ad18a-2
m2w64-isl: 0.16.1-2
m2w64-libiconv: 1.14-6
m2w64-libmangle-git: 5.0.0.4509.2e5a9a2-2
m2w64-libwinpthread-git: 5.0.0.4634.697f757-2
m2w64-make: 4.1.2351.a80a8b8-2
m2w64-mpc: 1.0.3-3
m2w64-mpfr: 3.1.4-4
m2w64-pkg-config: 0.29.1-2
m2w64-toolchain: 5.3.0-7
m2w64-tools-git: 5.0.0.4592.90b8472-2
m2w64-windows-default-manifest: 6.4-3
m2w64-winpthreads-git: 5.0.0.4634.697f757-2
m2w64-zlib: 1.2.8-10
mkl-service: 1.1.2-py35h051acba_4
msys2-conda-epoch: 20160418-1

Proceed ([y]/n)? y

libpython-2.1- 100% |###############################| Time: 0:00:04 9.69 MB/s
mkl-service-1. 100% |###############################| Time: 0:00:00 846.01 kB/s

(bayes) C:\Users\JIMSJOO>python
Python 3.5.3 |Anaconda custom (64-bit)| (default, May 15 2017, 10:43:23) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import pymc3 as pm
WARNING (theano.tensor.blas): Using NumPy C-API based implementation for BLAS functions.
C:\Users\JIMSJOO\Anaconda3\envs\bayes\lib\site-packages\h5py\__init__.py:36: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.
from ._conv import register_converters as _register_converters
>>> model=pm.Model()
>>> with model:
... mu1=pm.Normal("mu1",mu=0,sd=1,shape=10)
...
>>> with model:
... step=pm.NUTS()
... trace=pm.sample(2000,tune=1000,init=None,step=step,njobs=2)
...

C:\Users\JIMSJOO\Anaconda3\envs\bayes\lib\site-packages\pymc3\model.py:384: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.
if not np.issubdtype(var.dtype, float):
WARNING (theano.tensor.blas): Using NumPy C-API based implementation for BLAS functions.
C:\Users\JIMSJOO\Anaconda3\envs\bayes\lib\site-packages\h5py\__init__.py:36: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.
from ._conv import register_converters as _register_converters
23%|##################3 | 704/3000 [00:01<00:05, 446.05it/s]WARNING (theano.tensor.blas): Using NumPy C-API based implementation for BLAS functions.
35%|########################### | 1054/3000 [00:02<00:03, 492.33it/s]C:\Users\JIMSJOO\Anaconda3\envs\bayes\lib\site-packages\h5py\__init__.py:36: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.
from ._conv import register_converters as _register_converters
100%|#############################################################################| 3000/3000 [00:05<00:00, 576.51it/s]
>>>

가상개발환경을 주피터 노트북에서 사용하기 PYTHON


윈도우에서 아나콘다를 가지고 가상개발환경을 만들었는데, 콘솔이 아닌 주피터 노트북에서 사용하고 싶었다. 그러나 가상개발환경을 만들어 준다고 해도 편리하게 주피터 노트북에서 가상개발환경을 사용하도록 만들어 주지는 못하는 듯하다 (나중에 안 사실이지만, 아나콘다 루트의 기본 파이썬 버전을 사용하는 가상개발환경을 만드는 경우 자동으로 만들어 준다) 주피터노트북은 가상개발환경과 무관하게 아나콘다의 전역적인 개발환경을 염두에 두고 작동을 하도록 만든 듯하다.

구체적인 방법은 다음과 같다.
1. 아나콘다 프롬프트를 연 후 가상개발환경으로 들어간다.
activate py35


2. ipykernel을 설치한다
(py35) $ pip install ipykernel


3. C:\Users\사용자이름\Anaconda3\share\jupyter\kernels 밑에 가상개발환경을 위한 커널폴더를 만들고 kernel.json 파일을 생성한다.

기본적으로 python3 폴더가 있고 그안에 kernel.json파일이 있다. kernel.json파일에는 주피터 노트북에서 기본으로 사용할 수 있는 Python3 노트북의 설정이 여기 있는데, 그 내용은 다음과 같다.
{
"argv": [
"C:\\Users\\사용자이름\\Anaconda3\\python.exe",
"-m",
"ipykernel_launcher",
"-f",
"{connection_file}"
],
"display_name": "Python 3",
"language": "python"
}

우리가 만든 가상개발환경도 python3와 같이 똑같이 만들어 주는 것이 핵심이다. 가상개발환경을 위한 노트북용 폴더(폴더이름이 가상개발환경의 이름과 일치하지 않아도 된다)를 하나 만들고 kernel.json 파일을 추가해준다.

4. kernel.json 편집
kernel.json의 세 번째 행은 파이썬 실행파일이 있는 경로와 파일명이다. 보통 가상개발환경은 C:\Users\사용자이름\Anaconda3\envs 아래에 만들어 진다. 그리고 가상개발환경 폴더에 python.exe가 있다. 그리고 "display_name" 에는 주피터 노트북 이름을 적어준다, 이름은 가상개발환경의 그것과 달라도 된다.
{
"argv": [
"C:\\Users\\사용자이름\\Anaconda3\\envs\\py35\\python.exe",
"-m",
"ipykernel_launcher",
"-f",
"{connection_file}"
],
"display_name": "Zipline",
"language": "python"
}


5. zipline이라는 커널이 새로 생긴 걸 볼 수 있다

아나콘다에서 파이썬 개발환경 수정 PYTHON

개발과정중에 아나콘다가 여러 모로 편리한 점이 있는데, 늘 명령이나 자주 사용하지 않는 명령을 정리해보려고 한다.
1. 설치된 파이썬과 라이브러리 버전(기본버전은 버전앞에 *가 붙음)
conda search python


2. 가상환경 설치 및 파이썬 버전 설정-가령 py35라는 가상환경을 만들고 사용할 파이썬 버전을 3.5.3.으로 한다면
conda create -n py35 python=3.5.3 anaconda
참고: 가상환경 삭제 : conda remove --name py35 -all

3. 가상환경 사용
activate py35(윈도우즈의 경우)
source activate py35(맥, 리눅스의 경우)

4. 가상환경 종료
deactivate py35(윈도우즈의 경우)
source deactivate py35(맥, 리눅스의 경우)

5. 기본 파이썬 버전 지정
conda install python=3.5.3


베이즈통계로 짝사랑하는 상대방의 마음을 확인하는 법 Data science



사람 마음, 특히 내가 짝사랑하는 이성의 마음을 알고 싶은 것은 인지상정이죠. 스마트폰 앱중에는 짝사랑하는 상대방의 마음을 알려주는 앱이 있더군요. 그런데, 무슨 원리인지는 모르지만 앱이 자동으로 카톡 상대방에게 '~니가 너무 좋아' 하는 고백을 보내는 바람에 쪽팔리는 사태가 벌어진 리뷰가 재미있네요.


요즘 보고 있는 '세상에서 가장 쉬운 베이즈통계학 입문'이라는 책에는 초콜릿을 주는 직장동료가 나를 좋아하는 지, 아니면 그냥 주는 건지를 베이즈확률로 계산하는 예가 나옵니다.

문제설정
당신이 남성이라고 가정하자. 특정여성 동료가 자신에게 호감을 가지고 있는 지 알고 싶은 상황이다. 그런 와중에 당신은 밸런타인데이에 그녀로부터 초콜릿을 받았다. 이때 그녀가 당신을 진지하게 생각하고 있을 확률이 얼마라고 추정해야 할까?

여기에선 객관적인 자료(여자 마음에 대한 추측)가 없어 '이유불충분의 원리'를 적용하여 진심/논외로 나눠 각각 0.5의 확률을 부여하는 걸로 시작합니다.
'진심'은 그녀가 나에 대한 호감을 가진 것, '논외'는 그녀가 나를 그냥 직장동료정도로만 생각하는 것이죠.

그리고 조건부확률을 구해야 하는데, 이것은 설문조사 자료를 바탕으로 정하는 데, 통계적으로 평균 그녀들은 관심있는 상대에게 42.5% 확률로, 논외인 상대에게 22%의 확률로 초콜릿을 준다고 합니다.

사전확률과 조건부확률로 아래의 도표3-3과 같이 4가지의 세계(책에 따른 용어)로 나뉩니다.

그런데 운 좋게도 동료여성으로부터 초콜릿을 받았다고 합니다. 그래서 주지 않는다는 세계는 소거되고 남은 것은 "진심&준다"와 "논외&준다"가 남았습니다. 두 확률의 비율은 0.2:0.1 인데 모든 확률은 합쳐서 1.0 이어야 하는 정규화 규칙으로 이를 다시 계산하면

이 결과로부터 초콜릿을 준 그녀의 마음이 진심일 확률은 2/3 = 66%가 된다고 합니다. 처음에 50%라는 사전확률이 동료여성의 초콜릿을 준 행동을 관찰하게 됨으로써 약 66% 사후확률로 바뀌었습니다. 짝사랑만 하지 말고 확인해보시길 바랍니다. ㅎㅎ
이제 저도 짝사랑하는 그녀의 마음을 확인해볼까 합니다. 그런데 현실적으로 여자친구는 유니콘 같은 상상속의 동물 아닌가요?

워크시트 선택 영역을 재빨리 움직이는 방법 EXCEL/VBA


백 마디의 말보다 그림 한 장이면 충분한 경우도 있죠. 본능적으로 했던 것이지만 모르시는 분도 계실까봐...
[출처] Learn a Super Quick Way to Move Rows and Columns in Excel

페어트레이딩에 대한 짧은 글 금융공학

절대수익을 얻는 방법중 하나는 한 개의 자산을 매수하고 동시에 또 다른 하나의 자산을 매도하는 방법이 있다. 이를 Relative trading 또는 Pairs trading이라고 한다. 그러나 아무거나 사고 파는 것은 아니다. 매수/매도할 자산을 선택해야 하는 숙제가 남아 있다.

펀더멘탈 분석을 통해 저평가/성장가능성 높은 넘은 매수하고, 반대로 고평가/성장한계에 부닺친 넘은 매도하는 방법
통계적 분석으로 두 주식간의 괴리도가 벌어지거나 수렴하는 성질-평균회귀를 이용하는 방법

통계적 분석으로 지수보다 성과가 높은 포트폴리오를 매수하고 , 지수선물을 매도하거나 반대로 성과가 낮은 포트폴리오를 매도하고 지수선물을 매수하는 절대수익을 추구할 수 있다.

그러나 현실적으로 포트폴리오를 매도(공매도)하는 것이 쉽지 않다. 포트폴리오내 주식들을 일일이 원하는 수량만큼 빌리는 것도 수월하지 않고, 빌리는 비용을 지불해야 한다.

공격적으로 운용한다면 지수선물 대신 두 개의 포트폴리오를 매수/매도할 수도 있다.

1. 통계적 분석 방법
2. 회귀분석을 이용한 방법
3. 공적분 분석을 이용한 방법

1) 회귀분석을 이용한 방법
일반적인 회귀분석은 독립변수와 종속변수간의 관계를 식으로 풀어 미래를 예측하려는 알고리즘이다. 그러나 매수/매도하는 두 개의 종목은 어느 한 쪽이 독립변수이고 다른 한 쪽이 종속변수인 관계는 아니다. 직교회귀를 이용한 방법은 독립변수와 종속변수를 번갈아 바꿔 회귀분석을 실시한 후 기준선을 구하여 실제 값과의 직교거리의 괴리도를 이용하여 매매한다.


2) 공적분 분석을 이용한 방법
시계열을 이용한 분석으로 통계적 수치가 시간의 흐름에도 불구하고 일정하도록 하여(Stationary Process, 시불변) 분석한다. Non-Stationary Process 를 보이는 데이터를 변수들의 조합으로 Stationary Process로 바꾸는데, 이렇게 조합되는 변수들은 서로 Co-integrated되었다고 한다. 공적분 검정을 통해 시불변과정으로 바꿔 시계열분석을 한다.

흔히 co-integration에 대해 설명하는 예가 산책하는 주인과 강아지이다. 둘은 같은 방향으로 이동하지만 강아지는 주인 곁을 멀리 떠나지 않으면서 주변을 무계획적으로 돌아 다닌다. 따라서 강아지는 주인의 위치 정보를 제공하고 주인은 강아지의 위치를 알려주게 된다. 이때 주인과 강아지는 co-integration 되었다고 한다.


3) 분석시 고려할 사항
  • 분석대상 : 동조화 현상이 좋은 종목과 지수
  • 분석기간의 설정
  • 적용기간의 설정
  • 괴리도 설정 : 가령 추정치와 실제값의 잔차가 1.65*SD 이상 벌어지면 시작, 1.0*SD 이내로 돌아오면 포지션 청산
  • 수익률 계산방법
전체 데이터중 80%를 분석기간으로, 나머지 20%를 적용기간으로 분리한 뒤 모델링은 분석기간의 데이터만 가지고 수행하고, 모델의 성능은 적용기간로 평가하면 모델의 성능을 가장 적절히 평가할 수 있다. 전체 데이터를 모델링과 성능평가에 사용하면 데이터에 내재되어 있는 실제적 특징외에 데이터에 우연한 노이즈까지 반영한 모델을 만들게 될 위험이 있다. 과적합된 모델을 사용하게 되면 예측력이 떨어진다.

1 2 3 4 5 6 7 8 9 10 다음