2016년 8월 4일 목요일

AWS free tier 사용기 - 예상하지 못했던 과금

AWS 에 가입하고 무료로 제공 하는  EC는 tmicro 이다.
기본 저장 볼륨은 30GB 이지만

M$ Windows SERVER가 설치 되어 있는 이 서버는  가용 용량이 턱없이 부족하다.

여기서 첫번째 실수를 했다.

어디선가 웹에서 AWS에 볼륨 사이즈를 늘리는 것을 보고 볼륨 사이즈를 늘렸다.

무료 사용자라는걸 잠시 잊었다.

거기에 지금까지 설정한 세팅이 아쉬워서 EBS 볼륨 스냅샷까지 만들었다.

추가 볼륨을 만들고 스냅샷으로 볼륩을 복원해서 큰 용량의 서버를 구축 했다.

뒤늦게 과금 문제가 생각 나서 무료에 대한 정보를 읽어 보았다.
30GB만 무료인것이다.

다시 30GB로 용량을 돌려 놓고 꾸역 꾸역 적은 공간에 디스크 압축 설정 까지 해가면서
무료로 설정 하였다.

아뿔싸

잊은게 잇었다.
스냅샷!

결국 새벽4시에 문자를 받았다.
US$ 2.63 미국 Amazon w 승인

그렇다 스냅샷 조차 허용되지 않는다. 1GB가 무료?
스냅샷은 1GB만 무료인것이다.

스냅샷도 시원하게 delete 시켰다.

2016년 8월 3일 수요일

mac용 chm 앱 ReadCHM

갑자기 CHM 파일이 Windows 10 / Windows Server 2012 R2에서 내용을 볼수가 없다.


갑자기 가 아니라 이미 오래전 부 터 열리지 않고 있었는지 모른다.
좀 낡은 chm 파일을 봐야 하는데 정말 답답하게 되었다.


파일은 열리지만 내용이 하나도 안보 이는 현상이다.


아마존에 Windows SERVER나 페러럴에 Windows 10이나 모두 같은 현상인 걸로 봐서
최신 MS 윈도우에 HTML처리 방식에서 더 이상 지원하지 않는것인지 M$ windows 컴맹인 나로서는 어떻게 해결할 방법이 없다.

그래서 맥용 CHM 파일을 볼수 잇는 앱을 찾아 나섰다.

여러 앱을 설치 했지만 한글 인코딩을 지원하지 않는다.
모두 그러한 기능이 없다.




단 하나의 앱을 제외 하고 무료로 한글 인코딩이 지원되는 앱은 ReadCHM 오직 하나 였다.







이 훌륭한 무료 앱은 PDF컨버팅 까지 지원하지만 유료 버젼으로 업그레이드 하지 않으면 PDF로 변환은 되지만 워터마크가 새겨진 PDF파일이 생성된다.

하지만 뭐 이 정도만이라도 허접한 윈도우 도움말 보기보단 훨 좋다.




2016년 7월 31일 일요일

TMap API로 예상 소요시간을 구하려면?

애플지도, 구글지도 등등 여러 다른  지도에서도 경로 탐색이 가능 하고
자동차, 자전거, 도보에 따른 예상 시간을 구할 수 있을 것이다.

하지만 꼭집어서 TMap API로 해주세요. 이런 경우 삽질이 불가피 했다.

TMapOpenAPI PDF 문서를 보면 다음과 같이 되어 있다.

4.9.15. (NSDictionary*) findTimeMachineCarPathWithStartPoint: (TMapPoint*)startPoint
타임머신 자동차 길안내로 출발 혹은 도착시간을 예측한 자동차 길 안내정보를 제공한다. 반환된 정보는 NSDictionary 안에 포함이 되어 있고, 자세한 내용은 skpPlanetx.com 의 경로안내를 참조하면 된다. 주소는 https://developers.skplanetx.com/apidoc/kor/t-map/course-guide/geojson/ 이다.


Parameters
- (TMapPoint*) startPoint : 출발지점
Return
- https://developers.skplanetx.com/apidoc/kor/t-map/course-guide/geojson/ 참조
Example


당연히 네비게이션을 만들수 있는 TMap API를가지고 경로 안내는 물론 예상 도착 시간을 구할 수 있어야 하는데
설명이 너무 부족 하다.

https://developers.skplanetx.com/apidoc/kor/t-map/course-guide/geojson/
여기 사이트를 참조 하라?
응답 값으로 geoJSON이란 형태로 주어진 위치에 대한 경로 정보가 리턴 된다고 한다.

type
features --- type
geometry
properties -- totalTime

findTimeMachineCarPathWithStartPoint 메서드에 응답 NSDictionary도 이와 같다는 의미로 해석 하면 될 듯 하다.

결국 내가 구하고자 하는 것은 예상 소요시간이므로

let path = TMapPathData()

let startPoint = TMapPoint(lon: start_lon, lat: start_lat)
let endPoint = TMapPoint(lon: end_lon, lat: end_lat)

let date = NSDate()

var dict = path.findTimeMachineCarPathWithStartPoint(startPoint , endPoint: endPoint, isStartTime: true, time: date, wayPoints: nil)

let totalTime = (dict["features"]! as! NSArray)[0]["properties"]!!["totalTime"] as! Double


features의 NSArray중 첫번째에서 properties,그 하위 totalTime을 Double로 변환 시키면 totalTime을 구할 수 있다.

2016년 7월 16일 토요일

zipline 국내 종목 처리시 문제점 해결

    self.simulation_dt,
  File "c:\zipline-0.9.0\zipline\utils\events.py", line 209, in handle_data
    context.trading_environment,
  File "c:\zipline-0.9.0\zipline\utils\events.py", line 228, in handle_data
    self.callback(context, data)
  File "c:\zipline-0.9.0\zipline\algorithm.py", line 368, in handle_data
    self._handle_data(self, data)
  File "C:\Users\Administrator\OneDrive\Developement\SystemT\systemt\backtesting
.py", line 62, in handle_data
    ma5 = history(5, '1d', 'price').mean()
  File "c:\zipline-0.9.0\zipline\utils\api_support.py", line 51, in wrapped
    return getattr(get_algo_instance(), f.__name__)(*args, **kwargs)
  File "c:\zipline-0.9.0\zipline\utils\api_support.py", line 98, in wrapped_meth
od
    return method(self, *args, **kwargs)
  File "c:\zipline-0.9.0\zipline\algorithm.py", line 1270, in history
    return self.history_container.get_history(history_spec, self.datetime)
  File "c:\zipline-0.9.0\zipline\history\history_container.py", line 904, in get
_history
    raw=True
  File "c:\zipline-0.9.0\zipline\history\history_container.py", line 56, in ffil
l_buffer_from_prior_values
    nan_sids = pd.isnull(buffer_values[0])
IndexError: index 0 is out of bounds for axis 0 with size 0
Press any key to continue . . .


zipline 0.8.4
zipline 0.9.0

pandas_datareader를 이용해서 yahoo에서 AAPL 애플 주가를 얻은 다음
zipline 백테스팅 예제를 처리 하면 잘 동작 한다.

dataFrame에서 날짜 인덱스 부분을 UTC 시간으로 변경 하는 작업을 해주면 문제 없이 동작 한다.

하지만 국내 증시
나의 경우 직접 대신 증권 API를 통해서 일자별 시가, 고가, 저가, 종가를 얻어다가 DB를 구성 하고
이를 다시 로드 하여 dataframe을 구성해서

zipline에서 이용할 때 위와 같은 에러를 만났다.

대충 원인을 분석 하니 날짜 인덱스가 문제가 되는것으로 보인다.

그래서 pandas를 통해서 해당 종목을 yahoo에서 얻어서 처리를 해도 마찬가지 에러가 발생 한다.

우리나라 주식 거래일과 미쿡의 주식 거래일이 달라서 생기는 문제로 잠정 원인을 파악 했다.

그럼 해결방법은?

분석 시작 날짜로 부터 오늘의 데이터 까지를 대략 AAPL 즉 애플의 데이터 (미쿡 증시) 를 가져 온다음
종가 Adj Close 컬럼의 값을 실제로 내가 분석 하고 싶은 우리나라 종목에 종가로 교체 해 버리고

zipline을 처리 하니 동작 하더라

여기서 중요 포인트는 데이터 프레임의 개수를 맞추는 작업

    import pandas_datareader.data as web
    import datetime
    start = datetime.datetime(2010, 1, 1)
    end = datetime.datetime(2016,7,15)
    data  = web.DataReader("AAPL", "yahoo", start, end)
    data = data[['Adj Close']]
    data.columns = [code]
    data.head()
    data = data.tz_localize("UTC")

    df = makeDataFrame(code)
   
   
    df = df[['CLOSE']]
    data = data[len(data) - len(df):]  #데이터 프레임의 row 수를 맞추는 작업
    data[code] = np.where(1, df['CLOSE'], df['CLOSE'])    #DB에서 가져온 df의 CLOSE 컬럼을 AAPL의 종가 컬럼으로 교체
   
   
   
   
zipline이 아직 개발 단계에 문제점이 많지만 간편하게 백테스팅을 처리 할 수 있는 좋은 라이브러리 같다.

2016년 7월 14일 목요일

주가 분석 , 이평선 골든 크로스, 볼린져 밴드 하단 터치 이후 상승, MACD signal Cross 종목 찾기

https://github.com/sparrowapps/systemt

2016년 7월 14일 골든 크로스 결과만 보자면

sqlite> select * from MAGC;
0|A004560|현대비앤지스틸
1|A175330|JB금융지주
2|A004960|한신공영
3|A900110|이스트아시아홀딩스
4|A085310|엔케이
5|A000155|두산우
6|A016880|웅진
7|A059090|미코
8|A200780|비씨월드제약
9|A082740|두산엔진
10|A110570|넥솔론
11|A100030|모바일리더
12|A160550|NEW
13|A027050|코리아나
14|A083450|GST
15|A089600|나스미디어
16|A041440|에버다임
17|A200230|텔콘
18|A090990|코리아03호
19|A065440|이루온
20|A079650|서산
21|A008700|아남전자
22|A024120|KB오토시스
23|A050760|에스폴리텍
24|A008970|동양철관

sqlite> 

네이버님의 골든크로스 결과보다 몇몇 종목이 더 나 왔다.


#-*- coding: utf-8 -*-

import pandas as pd
from pandas import Series, DataFrame
import sqlite3

import numpy as np

from logger import get_logger
from stockcode import get_code_list
from settings import START_DATE
from cp_constant import *
import win32com.client

def checkData( cursor, table_name ):
    row = cursor.execute("SELECT 1 FROM sqlite_master WHERE type='table' AND name='{}'".format(table_name)).fetchone()
    if row is None: return False
       
    row = cursor.execute("SELECT COUNT(*) FROM '{}'".format(table_name)).fetchone()
    if row is None : return False

    return True

def makeDataFrame( code ):
    with sqlite3.connect("price.db") as con:
        cursor = con.cursor()
        table_name = code
       
        if checkData( cursor, table_name ) == False: return False
       
        df = pd.read_sql("SELECT * FROM '{}'".format(table_name), con, index_col=None)
        return df

def isMAGoldCross( df, MA1 = 20, MA2 = 60 ):
    df['short_ma'] = pd.rolling_mean(df['CLOSE'],MA1)
    df['long_ma'] = pd.rolling_mean(df['CLOSE'],MA2)
    df['signal'] = 0.0
       
    if len(df) < MA2 * 4 : return False
       
    df['signal'][MA1:] = np.where(df['short_ma'][MA1:] > df['long_ma'][MA1:], 1.0, 0.0)
    df['positions'] = 0.0
    df['positions'] = df['signal'].diff()
       
    if df['signal'][len(df)-1] == 1 and df['positions'][len(df)-1] == 1:
        return True
    else:
        return False

def isBBandSignal( df, period = 20):
    df['Bol_upper'] = pd.rolling_mean(df['CLOSE'], window=period) + 2* pd.rolling_std(df['CLOSE'], period, min_periods=period)
    df['Bol_lower'] = pd.rolling_mean(df['CLOSE'], window=period) - 2* pd.rolling_std(df['CLOSE'], period, min_periods=period)
    df['signal'] = 0.0
    df['signal'] = np.where(df['Bol_lower'] > df['CLOSE'], 1.0, 0.0)
    df['positions'] = 0.0
    df['positions'] = df['signal'].diff()

    if len(df) < 2: return False

    if df['signal'][len(df)-2] == 1 and df['positions'][len(df)-2] == 1:
        if df['signal'][len(df)-1] == 0 and df['positions'][len(df)-1] == -1.0:
            return True
        else:
            return False
    else:
        return False

def isMACDSignal( df, n1 = 12, n2= 26, c= 9):
    df['MACD'] = pd.ewma(df['CLOSE'], span=n1) - pd.ewma(df['CLOSE'], span=n2)
    df['MACD_Signal'] = pd.ewma(df['MACD'], span=c)
    df['signal'] = 0.0
    df['signal'] = np.where(df['MACD'] < df['MACD_Signal'], 1.0, 0.0)
    df['positions'] = 0.0
    df['positions'] = df['signal'].diff()

    if df['signal'][len(df)-1] == 1 and df['positions'][len(df)-1] == 1:
        return True
    else:
        return False

def run():
    with sqlite3.connect("analyze.db") as con:
        cursor = con.cursor()

        code_magc = {'CODE':[],
                     'NAME':[]}
        code_bb   = {'CODE':[],
                     'NAME':[]}
        code_macd = {'CODE':[],
                     'NAME':[]}

        for code, name in get_code_list():
            df = makeDataFrame( code )
            res = isMAGoldCross( df, 20, 60 )
            if res == True:
                code_magc['CODE'].append(code)
                code_magc['NAME'].append(name)
                get_logger().debug("MA20, MA60 Golden Cross {}{}".format(code,name))

            res = isBBandSignal( df, 20 )
            if res == True:
                code_bb['CODE'].append(code)
                code_bb['NAME'].append(name)
                get_logger().debug("BBnad lower after up {}{}".format(code,name))

            res = isMACDSignal( df, 12, 26, 9)
            if res == True:
                code_macd['CODE'].append(code)
                code_macd['NAME'].append(name)
                get_logger().debug("MACD sig {}{}".format(code,name))

        magc = DataFrame(code_magc)
        bb   = DataFrame(code_bb)
        macd = DataFrame(code_magc)
        magc.to_sql("MAGC", con, if_exists='replace', chunksize=1000)
        get_logger().debug("MAGC {} saved.".format(len(magc)))
        bb.to_sql("BB", con, if_exists='replace', chunksize=1000)
        get_logger().debug("BB {} saved.".format(len(bb)))
        macd.to_sql("MACD", con, if_exists='replace', chunksize=1000)
        get_logger().debug("MACD {} saved.".format(len(macd)))

if __name__ == '__main__':
    run()

python pandas_datareader yahoo 파이낸스 삽질기


코스콤에서 주식 코드를 얻어다가 yahoo 파이넨스에 pandas를 이용해서 주가 데이터를
가져 와서 sqlite  데이터를 구축 하려고 했다.

이렇게 가져온 데이터를 다시 pandas 데이터 프레임으로  sqlite로 부터 읽어 들여 분석을
하면 이동평균선 골든 크로스 등을 찾아 낼 수 있을 거라 생각 했다.

그런데 이상하게 동원이란 종목이 분석에 문제를 일으킨다.


>>> import pandas_datareader.data as web
>>> df = web.DataReader("003580.KS", "yahoo", "2016/06/01", "2016/07/13")
>>> print (df)
            Open  High   Low  Close  Volume  Adj Close
Date                                                
2016-06-01  1854  1854  1802   1814   45100       9070
2016-06-02  1866  1866  1804   1830   35200       9150
2016-06-03  1850  1874  1792   1854   31100       9270
2016-06-06  1854  1854  1854   1854       0       9270
2016-06-07  1840  1878  1822   1846   22900       9230
2016-06-08  1846  1846  1784   1814   26700       9070
2016-06-09  1780  1868  1780   1856   46500       9280
2016-06-10  1834  1870  1800   1832   20900       9160
2016-06-13  1800  1828  1772   1812   17700       9060
2016-06-14  1780  1800  1680   1758   25400       8790
2016-06-15  1740  1812  1724   1732   16600       8660
2016-06-16  1720  1788  1694   1730   16700       8650
2016-06-17  1730  1738  1602   1644   34900       8220
2016-06-20  1630  1670  1620   1638   29200       8190
2016-06-21  1650  1668  1638   1656   11300       8280
2016-06-22  1626  1696  1626   1660    7400       8300
2016-06-23  1632  1666  1630   1660   14000       8300
2016-06-24  1666  1676  1450   1550   77000       7750
2016-06-27  1486  1626  1482   1626   37600       8130
2016-06-28  1580  1694  1564   1690   32400       8450
2016-06-29  1688  1738  1622   1690   24000       8450
2016-06-30  1660  1762  1660   1762   35200       8810
2016-07-01  1762  1780  1726   1780   19600       8900
2016-07-04  1768  1790  1742   1760    6300       8800
2016-07-05  1734  1778  1732   1758   14100       8790
2016-07-06  1740  1740  1684   1720   14300       8600
2016-07-07  1780  1780  1702   1740   12900       8700
2016-07-08  1720  1784  1698   1740   24700       8700
2016-07-11  8400  8660  7630   8030  268800      40150
2016-07-12  7850  8400  7850   8350  106900      41750
2016-07-13  8500  8500  8250   8300   40000      41500




위에서 데이터를 보면 7월 8일 까지 1700원 때이던 데이터가 갑자기 8400원대로 변경 된다.
문제가 있다.

거래량도 갑자기 증가 한다.

야후 파이낸스에 데이터를 믿을수가 없다.

문제는 또한 KOSDAQ종목은 데이터가 없다.

이는 구글 파이낸스도 마찬가지다.

하여 결국 대신 증권 API를 이용해서 코드 부터 주식 과거 데이터를 구축 하는 코드로 변경 하였다.


야후 파이낸스도 믿을게 못된다.


2016년 6월 9일 목요일

XCode swift "Command failed due to signal: Segmentation fault: 11 해결 방법

XCode swfit 컴파일러가 컴파일중에 세그먼테이션 폴트가 발생하면 어떻게 해결 해야 하는가?



어떤 라인이 문제가 있는지 어떤 코드가 문제인지 찾아 주지도 못한다.

심지어 이런 상황에서 버그를 리포트 하라고 에디터 상단에 아래와 같은 화면이 표시 되기도 한다.




에디터는 신텍스 하이라이트가 실행 되지 못하고 모든 텍스트가 흑백으로 표시 될때도 있다.





XCode의 버젼은 7.3.1이다.


문제의 코드는 위에 주석처리 한 코드 아래의 코드가 문제를 일으키는 코드이다.

recentlAddr은 아래와 같이 선언 되어 있다.

var recentlAddr = [[String:AnyObject]]()

if 문으로 바로 비교를 들어가면 Xcode swift 컴파일러가 문제를 일으키는 것으로 보인다.

더많은 케이스가 있겟지만 내가 찾은 케이스는 이런 경우 이다.

위에 올바른 코드와 같이 

func bookmarkButtonClick(sender : UIButton) {
        let bookmark = self.recentlAddr[sender.tag]["bookmark"] as! String
        
        if bookmark == "1" {
            return
        }
        recnetTobookmark(sender.tag, bookMarkType: 3)
    }

이렇게 수정하면 아무런 문제 없이 컴파일이 잘되고 문제가 없다.

결론
 XCode 컴파일러의 Segmentation fault 11이 발생하면 그래도 코드를 유심히 찾아 봐라!