'분류 전체보기' 카테고리의 글 목록 :: Horizontal Grays S2

이쪽 개발일을 하다보면 아무래도 값에 대한 검증을 시리얼 포트로 입력받는 경우가 많다.

지금하고 있는 일에도 역시나 꼭 필요한 부분인데

실시간으로 경향을 파악할 때 좋은 툴로 Arduino IDE의 시리얼 플로터를 종종 사용한다.

 

그런데 언제 바뀌었는지 모르겠지만 Arduino IDE 업데이트 하라고 떴길래 그냥 하고 시리얼 플로터를 사용했더니

X축 값의 범위가 너무 좁아졌다. - 예전에 분명히 500개가 표시되었던 걸로 기억하는데 지금은 50개 밖에 표시가 안된다.

 

지금 표시하는 데이터가 하나에 10ms 이다보니 50개로 하면 0.5초 그러다보니 데이터가 너무 쉭쉭 지나가버린다.

 

이래선 도무지 데이터 확인이 어렵다.

 

그런데 아무리 뒤져도 Arduino IDE에는 이에 대한 설정을 하는 게 없다.

분명 ini 파일이던 뭐던 건드릴수 있을것 같은데 해서 찾은 방법

 

아래와 같이 Arduino IDE가 설치된 폴더안의 해당 폴더로 들어가면

C:\Users\유저\AppData\Local\Programs\Arduino IDE\resources\app\node_modules\arduino-serial-plotter-webapp\build\static\js

 

main.35ae02cb.chunk.js 파일이 있는데

이 파일을 편집기로 열고 '찾기'로 "U=Object(o.useState)" 를 찾는다.

 

그럼 현재 아래 그림과 같이 해당값이 50으로 되어있는 것을 볼 수 있다.

이를 예전처럼 500으로 수정/저장 한다.

U=Object(o.useState)(500)

그리고 Arduino IDE를 다시 실행하고 시리얼 플로터를 실행해보면

위 그림처럼 X축의 범위를 500까지 표현해주는 것을 볼 수 있다.

 

그 이상의 값까지 설정해보진 않았고 이정도면 나한텐 충분했다.

일이 일인만큼 키보드에 아무래도 관심이 많다.

뭐 그렇다고 엄청 고가에 투자하거나 그러진 않고 적당한 수준의 기계식 키보드를 좋아한다.

 

무조건 기계식일 필요는 없고 딱히 설명하긴 어렵지만 여튼 써봐야 아는.. 

(하긴 누구에게나 그렇겠지만)

 

그래서 기계식이 아니지만 씽크패드 노트북의 키감도 매우 좋아한다.

T42, X60, X201, X220 저마다 조금씩 다른 키감이지만 매우 좋아해서 소유했었다.

조금은 아쉽지만 X230도 나쁘지 않았다.

 

지금까지 쓴 기계식 키보드는

Corsair K70 RGB 체리 적축 : 키보드 자체는 만족스러운데 두꺼운 이중케이블이 불편하다.

Keymove DK66 : 기계식 무선 블루투스 키보드가 저렴하게 나와서 직구했는데  66키의 불편함, 무선인데 배터리 광탈로 거의 안씀

COX CK800 카일 광축 클릭 : 키감 자체는 매우 만족스러우나 소음때문에 이건 정말 집에서만 써야한다. 이거 아니라도 기계식은 집에서만 쓰길 권장, 그리고 저가형 특유의 통울림은 불만족

 

그 와중에 최근에 중국제 저렴하게 잘나오는 키보드들의 얘기를 종종 듣고 보아서 관심을 가지고 있었다.

- Anne Pro 2 라던가. Dareu A98 이라던가 - 

그러다 최근에 타오바오 딜로 올라오고 바로 큐텐에 뜬 저렴한 VGN V98 시리즈를 보았다.

V98 이 4만원정도

V98 Pro는 6만원대

V98 Pro Box는 8만원대

 

나는 왼손과 오른손에 각각 마우스를 쓰고 있어서 이왕이면 작은키보드가 좋은데 또 넘버패드가 있는 키보드가 좋다.

현실적으로 이 모든걸 만족하는 키배열은 없다고 생각했는데 최근에 98키가 이런 부분을 만족시켜준다.

V98과 V98 Pro의 차이는 배터리가 4000/8000 이고 키캡이 ABS/PBT  

그리고 가스킷이니 윤활축이니 이런건 사실 잘 모른다.

여튼 V98 Pro로 구매했다.

 

개봉

와.. 생각지도 못한 그림이 ㅋ 98 Pro라고 98%

 

키보드는 정말 예쁘다. 유선연결/충전 용 케이블, 키 리무버, 여분 축, 보증서, 설명서(중국어) 그리고 또 무슨 게임캐릭터 스티커까지 ㅋㅋ 있을건 다있다.

 

밝은곳에선 잘 안보이는데 LED도 RGB, 다시봐도 키보드는 참 이쁘다.

 

이 키보드의 장점 중 하나가 유선연결/ 무선 수신기/ 3개의 기기까지 블루투스로 연결 가능 한 점이다.

 

키감은 부드럽고 통울림도 없는데 개인적으론 클릭감이 없어서 좀 아쉽다. 난 클릭축을 좋아하는것 같다.

 

실제로 받아서 사용하고자 하니 문제가 있다.

 

1. 한영키 또는 우측 Alt 키의 부재

 - 당연히 Fn키를 맵핑하면 될것 같았는데 Fn키는 키보드 자체의 기능만을 컨트롤 하는것 같다. OS로 키코드 값이 안넘어온다. 

 - 많이 쓰던 방법인 Shift + Space로 변경해서 사용해야겠는데 레지스트리 건드리지 않았고 아래 링크의 프로그램으로 간단히 해결 JwShiftSpaceKey

 (이 방법이 아니고 윈도우 설정에서 바꾸는 방법이 있는데 나는 현재 노트북을 쓰고 있어서 설정에서 바꾸면 노트북 자체의 한영키가 안먹어서...)

윈도우 쉬프트 스페이스 한영전환 프로그램 jwShiftSpaceKey :: 바다야크 (badayak.com)

 

윈도우 쉬프트 스페이스 한영전환 프로그램 jwShiftSpaceKey

jwShiftSpaceKey 3.7 업그레이드 jwShiftSpaceKey의 한영모드 알리미의 크기가 크다는 말씀이 있으셔서 조금 작게 만들고, 윈도우 화면 배율에 따라 한영 글자가 엉뚱한 위치로 출력되지 않도록 수정했습

badayak.com

 

2. 블루투스 연결 방법은?

설명서가 중국어다 보니 대체 블루투스 연결 방법을 모르겠다. 열심히 검색해보니 아래와 같은 방법이었다.

 

키보드 왼쪽에 모드 변경 스위치가 있는데 무선수신기/유선연결/블루투스 순서이다. 이걸 블루투스로 놔두고

Fn 키 + 1 (2,3까지 3개의 기기 연결 가능)를 누르고 있으면 BT라고 쓰여있는 LED가 빠르게 깜빡거린다.

이때 페어링 하면 된다.

 

3. 왼쪽 Alt와 Win키가 뒤바뀌어 있슴

사실 처음 받았을 때 왼쪽 Alt와 Win키가 뒤바뀌어 있었다.. 이건 대체 뭔지

이부분은 VGN사이트에서 펌웨어 업데이트하고 (이걸로 해결되었던것 같은데 어제 작업해서 기억이 ^^;)

드라이버 프로그램 다운로드 받고 프로그램 실행시키면 여튼 된다.

游戏动力 - 专业游戏媒体 游戏打折促销信息全查询 驱动下载 (vgn.cn)

 

游戏动力 - 专业游戏媒体 游戏打折促销信息全查询 驱动下载

 

www.vgn.cn

중국어로 나와있는데 브라우저에서 한글로 번역해서 보면 어렵진 않다.

 

드라이버 프로그램 V98 Pro 실행시키면 (키보드는 반드시 유선 연결이 되어야 한다.)

라이트도 설정할수 있고 키 셋팅, 매크로 등등 설정 가능하다.

* 완전 초보의 관점에서 하나씩 해보는 것이니 상세한 설명은 기대하지 마세요~

지난번의 xformers 관련 에러나 out of memory 관련 에러나 모두 argument로 해결이 되었다.

이 Argument에 대해서는 stable diffusion web-ui 를 다운받았던 github에 자세히 나와있었다.

Command Line Arguments and Settings · AUTOMATIC1111/stable-diffusion-webui Wiki · GitHub

 

Command Line Arguments and Settings

Stable Diffusion web UI. Contribute to AUTOMATIC1111/stable-diffusion-webui development by creating an account on GitHub.

github.com

지금은 봐도 뭔소린지 사실 잘 모르겠다.

 

여튼 argument 관련 셋팅에 대해 찾아보다 많이 쓰는 셋팅을 찾았는데 아래와 같았다.

set COMMANDLINE_ARGS= --xformers --opt-split-attention --autolaunch --enable-insecure-extension-access --medvram

 

하나씩 보면

--xformers : enable xformers for cross attention layers -

--opt-split-attention : force-enables Doggettx's cross-attention layer optimization. By default, it's on for cuda enabled systems.

--autolaunch : open the webui URL in the system's default browser upon launch

--enable-insecure-extension-access : enable extensions tab regardless of other options

--medvram : enable stable diffusion model optimizations for sacrificing a little speed for low VRM usage
해석해봐도 뭔소린지 알 수 있는건

autolaunch 는 CMD에서 webui-user.bat 실행하면 자동으로 브라우저로 webui 올라온다는거고

--medvram 은 속도는 조금 떨어질지언정 VRAM의 사용량을 줄이게 해준다는거 그래서 이게 out of memory 오류를 해결해준것이었다.

여튼 이렇게 일단 argument setting을 마치고 webui 설정들을 여기저기 사이트 찾아서 수정해보았다.

 

그리고 Model이라는게 그림체를 설정하는 역할을 하는데 애니메이션처럼 그릴것인지 실사처럼 그릴것인지 등등 을 결정한다. 이 model 관련 파일을 다운받아서 실행하는하는데 검색해보니 여러 종류가 있었다. 용량도 상당하다.

일단 몇가지 모델에 따른 예는 좀 있다가 만들어보고

 

Stable Diffusion으로 만든 그림을 보면 질문들에 프롬프트가 뭐냐는 질문이 많았다. 이게 그 이렇게 만들어라 하는 명령어 같은데

Positive Prompt : 이렇게 만들어라

Negative Prompt : 이렇게 만들진 말아라 

기본적으로 이렇게 두개가 있고 당연하겠지만 찾아보니 엄청나게 많은 종류가 있어 다 퍼오기도 힘들다.

 

간단한 예시가 있어 하나 가져오면

Positive Prompt : masterpiece, best quality, 1girl, black hair, golf course

 - 좋은 퀼러티의 검은머리 여자 한명이 골프장 배경으로 만들어라

 

Negative prompt: lowres, bad anatomy, bad hands, text, error, missing fingers, extra digit, fewer digits, cropped, worst quality, low quality, normal quality, jpeg artifacts, signature, watermark, username, blurry, artist name

 - 안좋은 퀼리티나 일반으로 만들지 말고, 손 나쁘게 만들지 말고 사인이나 유저이름 나오게 하지 말고 등등)

 

Steps: 28, Sampler: DPM++ 2M Karras, CFG scale: 11, Seed: 2623692471, Face restoration: CodeFormer, Size: 512x768, Model hash: fc2511737a, Model: chilloutmix_NiPrunedFp32Fix, Denoising strength: 0.6, ENSD: 31337, Hires upscale: 1.5, Hires steps: 14, Hires upscaler: R-ESRGAN 4x+ Anime6B

 

샘플링 Step은 28로 - Step 수가 클수록 퀼리티가 좋아지고 속도는 느려진다.

CFG Scale 은 11로 - CFG Scale이 높을수록 프롬프트를 얼마나 따를지를 결정한다. 

Seed는 AI의 계산에 변수를 줘서 다양한 결과물이 나오도록 하는 값이다.

기타 등등...

 

우선 이걸 기본 프롬프트로 하고 아래 모델을 다운받아서 일단 만들어보자.

 

모델은 아래 두가지만 해보려고 한다.

 

1. orange mix : 애니메이션 같은 그림

 

WarriorMama777/OrangeMixs at main (huggingface.co)

 

* 여기 파일명을 보면 XXX_hard, XXX_nfsw, XXX_sfw 이렇게 뒤의 글자가 다른것을 알수 있다. 

hard : 글자 그대로 과격한 성행위 묘사

nsfw : not safe for work 일할때 안전하지 않아 즉 후방주의 정도 되겠고

sfw : safe for work 건전한 그림 이다.

 

2. ChilloutMix : 실사같은 그림

ChilloutMix | Stable Diffusion Checkpoint | Civitai

 

ChilloutMix | Stable Diffusion Checkpoint | Civitai

This model has been republished and its ownership transferred to Civitai with the full permissions of the model creator. They have asked that all i...

civitai.com

 

 

일단 orange mix로 만들어본거

masterpiece, best quality, 1girl, black hair, golf fieldNegative prompt: lowres, bad anatomy, bad hands, text, error, missing fingers, extra digit, fewer digits, cropped, worst quality, low quality, normal quality, jpeg artifacts, signature, watermark, username, blurry, artist nameSteps: 28, Sampler: DPM++ 2M Karras, CFG scale: 11, Seed: 918993248, Face restoration: CodeFormer, Size: 512x768, Model hash: 0873291ac5, Model: AbyssOrangeMix2_nsfw, Denoising strength: 0.6, Hires upscale: 1.5, Hires steps: 14, Hires upscaler: R-ESRGAN 4x+ Anime6B Time taken: 4m 6.20sTorch active/reserved: 1888/2456 MiB, Sys VRAM: 4096/4096 MiB (100.0%)

4분씩 걸리네.. 그나저나 뭘 들고 있는거냐? 이게 nfsw 로 만든거

 

masterpiece, best quality, 1girl, black hair, golf fieldNegative prompt: lowres, bad anatomy, bad hands, text, error, missing fingers, extra digit, fewer digits, cropped, worst quality, low quality, normal quality, jpeg artifacts, signature, watermark, username, blurry, artist nameSteps: 28, Sampler: DPM++ 2M Karras, CFG scale: 11, Seed: 602985742, Face restoration: CodeFormer, Size: 512x768, Model hash: 038ba203d8, Model: AbyssOrangeMix2_sfw, Denoising strength: 0.6, Hires upscale: 1.5, Hires steps: 14, Hires upscaler: R-ESRGAN 4x+ Anime6B Time taken: 3m 10.00sTorch active/reserved: 1888/2654 MiB, Sys VRAM: 4096/4096 MiB (100.0%)

이건 sfw로 만든거.. 대체 골프클럽을 장난감을 들고 있는 건가? 

 

 

자 이제 실사같은 그림을 만든다는 chilloutmix를 써서 해보자.

masterpiece, best quality, 1girl, black hair, golf fieldNegative prompt: lowres, bad anatomy, bad hands, text, error, missing fingers, extra digit, fewer digits, cropped, worst quality, low quality, normal quality, jpeg artifacts, signature, watermark, username, blurry, artist nameSteps: 28, Sampler: DPM++ 2M Karras, CFG scale: 11, Seed: 1393579719, Face restoration: CodeFormer, Size: 512x768, Model hash: fc2511737a, Model: chilloutmix_NiPrunedFp32Fix, Denoising strength: 0.6, Hires upscale: 1.5, Hires steps: 14, Hires upscaler: R-ESRGAN 4x+ Anime6B Saved: 00002-1393579719.png
masterpiece, best quality, 1girl, black hair, golf field Negative prompt: lowres, bad anatomy, bad hands, text, error, missing fingers, extra digit, fewer digits, cropped, worst quality, low quality, normal quality, jpeg artifacts, signature, watermark, username, blurry, artist name Steps: 28, Sampler: DPM++ 2M Karras, CFG scale: 11, Seed: 2158228535, Size: 512x768, Model hash: fc2511737a, Model: chilloutmix_NiPrunedFp32Fix

face restoration 옵션과 hires.fix 옵션을 주지 않아 업스케일 되지않은 사이즈로 나왔다.

 

확실히 지난번에 비하면 꽤 좋아졌다!
다만 내 그래픽카드의 한계인지 그림 한장 만들면 반드시 하단의 reload ui를 해줘야 했다.

안그러면 또 out of memory...

 

 

어제에 이어 오늘은 프롬프트를 이래저래 해볼 요량으로 다시 webui-user.bat 를 실행시켰다.

어제 보단 확실히 빠르게 실행되긴 하는데 그래도 1분 정도는 걸리는것 같다.

그런데 가만히 보니 Error가 하나 있다.

No module 'xformers'. processding without it.

실행이 안되는건 아닌데 어제의 그 엉망인 결과물이 혹시 이때문은 아닌가 싶어 검색해보았다.

 

일단 xformers가 결과물의 퀄리티를 높여주는 것은 아니고

Nvidia GPU에서만 사용되는 기능으로 이미지의 생성속도를 높이고 VRAM 사용을 줄여 이미 생성시간을 단축시키는 역할을 한다고 한다.

 

비록 1050ti 지만 아니 그러니까 더욱 생성속도를 높이는게 맞지 않겠나 싶어 일단 시도해보기로 한다.

 

아래 방법은 실패했다 점선은 패스하고 일단 webui-user.bat 파일의 arg 옵션에 --xformers 해서 동작시켜보는게 좋다.

-------------------------------------------------------------------------------
Xformers · AUTOMATIC1111/stable-diffusion-webui Wiki · GitHub

 

Xformers

Stable Diffusion web UI. Contribute to AUTOMATIC1111/stable-diffusion-webui development by creating an account on GitHub.

github.com

 

여기에 자세히 나와이어 최대한 그대로 따라해보았지만 (이 과정에서도 우여곡절이 좀 있었다)

문제가 생겼다. T.T

그렇다고 실행이 안되는건 아니었는데

 

Generate를 해보니

안된다.. 그나마도 ㅠㅜ

일단 다시 처음부터 시작해보기로 한다.

 

파이썬과 git는 냅두고

webui 폴더 만 삭제해서 재설치 해보자.

 

-----------------------------------------------------------------

webui 재설치 후 webui-user.bat 실행

여전히 No module 'xofrmers' 나온다.

혹시나 전처럼 generate 자체가 안될까봐 실행해보니

그래도 이번엔 생성이 되었다. 걸린시간은 48.59초

 

자 이제 xformers 문제를 해결해보자.

검색해보니 webui-user.bat 파일 안에 argument에 --xformers 를 입력해주면 된다고 나온다.

이렇게 해주고 다시 실행

오오 이번엔 별문제 없이 잘 되었다.

처음에 한 삽질은 왜 한걸까? 아님 그 덕에 한번에 된건지 정확히 모르겠다.
뭐 vs studio 깔고 cuda 깔고 이런거 하기전에 --xformers 먼저 붙여보길 추천한다.

 

그럼 속도 향상은 있을까?

이런.. 이미지를 생성하다가 오류.. OutOfMemoryError. CUDA out of memory 

일단 내 GPU 메모리는 4G 인데 이미 2.27G 할당되어있고 pytoch에서 2.4G 예약되어 있어서 그렇다고 나온다.

이걸 또 해결해봐야지.

 

검색해보니 시스템 가상메모리 늘려보란다.

일단 넉넉하게 늘려보았다.

 

그리고 다시 실행하니 된다.

여기서 의문은 GPU 메모리 관련 오류인데 시스템 메모리를 늘려서 해결이 된게 맞는가 싶은데 여튼 된다.

* 2023.4.19 추가 argument, model 들을 추가해서 그림의 퀄리티를 높여가는 과정에서 동일하게 Out of Memory 증상이 나왔다. 즉 시스템메모리를 페이징으로 늘리는것은 해결책이 아니다.

argument에 --medvram 을 붙이면 해결되었다.

 

34초 걸림

 

34초

역시 34초 걸림 - 이게 골프치는 여자 맞어? ㅋㅋㅋ

 

일단 되는것 같다. 다른 명령어를 한번 넣어보자. "pretty girl who driving sports car"

이건 뭐 여자가 차를 친거 같다. 차가 사람을 치는게 아니고 --;

이건 좀 잘 나왔다.

모두 34초 걸렸다.

 

시간은 10여초 줄인것 같고 생성되는 이미지의 질은 별로 안변한것 같다.

여튼 동작을 하니 프롬프트 관련은 다음에 다시 해보자!

 

* Golf 관련 데이터가 적은가 Car에 비하면 이미지가 형편없다. ㅋ

지금 회사에서 개발하고 있는 제품중 nRF52832를 이용하는게 있다.
나름 최대한의 전송속도와 전송량이 필요해서 테스트용 Central / Perpheral 기기 만들어서 테스트 중인데
막상 체크해보면 max throughput 은 안되는것 같다. 뭐 무선의 한계일수도 있고 펌웨어 문제일수도 있고

여튼 peripheral 에서 central로 전송되는 실제 속도등을 확인해보고자 sniffer를 만들어서 설치해보기로 한다.

 

여기서 nRF sniffer란 Central - Peripheral 사이의 무선 패킷을 캡춰하는 프로그램이라고 할 수 있겠다.

정확한 내용은 아래

nRF Sniffer for Bluetooth LE

The nRF Sniffer for Bluetooth® LE is a useful tool for learning about and debugging Bluetooth Low Energy (LE) applications. It provides a near real-time display of Bluetooth packets that are sent between a selected Bluetooth Low Energy device and the device it is communicating with, even when the connection is encrypted.

Nordic Semiconductor Infocenter

 

Nordic Semiconductor Infocenter

 

infocenter.nordicsemi.com

 

1. sniffer  hex파일 다운로드

nRF Sniffer for Bluetooth LE - Downloads - nordicsemi.com

 

nRF Sniffer for Bluetooth LE - Downloads

Nordic Semiconductor

www.nordicsemi.com

 최신이 4.1.1이 나와있어서 그걸로 다운로드 받았다.

 

압축파일을 풀면 여러 폴더가 있는데 그중 hex라는 폴더에 들어가서 맞는 hex 파일을 다운로드 한다.

나는 지금 가지고 있는게 nrf52 DK가 있어서 여기에 다운로드 했다.

다운로드는 nrf connect의 programmer를 이용했다.

별 문제없이 hex파일은 잘 다운로드 되었다.

 

그리고 문서를 보면 Wireshark를 설치하라고 나온다.

 

2. Wireshark 설치
이게 뭐냐면 무선 traffic을 캡춰하고 읽을수 있는 포맷으로 만들어 주는 무료 소프트웨어다.

아래의 Wireshark 페이지에서 다운로드 받아서 설치한다. 현재 4.0.5 버전이 최신이다. 

Wireshark · Download

 

Wireshark · Download

Wireshark: The world's most popular network protocol analyzer

www.wireshark.org

그리고 nRF sniffer capture tool을 Plug-in 한다.

 

3. nRF sniffer capture tool plug-in

 1) wireshar의 외부 플러그인으로 nRF Sniffer capture를 설치하려면 우선 Python이 설치되어 있어야 한다.

 2) 나는 python이 이미 설치되어 있어 Pass

python이 설치되어 있다면 1. 에서 sniffer 다운로드하여 zip 파일을 푼 폴더에 들어가면 extcap 폴더가 있는데 여기서 명령프롬프트를 실행시킨 후

 py -3 -m pip install -r requirements.txt

명령을 실행하면 필요 파일들이 설치된다.

 

 

wireshark가 설치된 폴더 중 extcap 폴더로 이동한다. 설치할때 설치폴더 확인하거나 미처 못했다면 wireshark 실행하고 help-about Wireshark 에서 Folders Tab을 보면 아래와 같이 폴더위치가 표시된다.

   여기서 Global Extcap path에 나와있는 파란색으로 되어있는 경로를 더블클릭하면 extcap 폴더가 열린다.

그러면 아까 Sniffer의 extcap 폴더의 모든 파일을 wireshark의 extcap 폴더로 복사한다.

 

wireshark의 extcap 폴더에서 명령프롬프트 실행시켜 다음 명령어로 wireshark external capture plugins 할수 있도록 한다.

nrf_sniffer_ble.bat --extcap-interfaces

wireshark 프로그램에서 Capture / Refresh Interfaces 를 실행하거나 F5를 누르면 nRF Sniffer for Bluetooth 인터페이스가 보인다

 

여기서 View / Interface Toolbars / nRF Sniffer for Bluetooth LE를 선택하면 준비 완료

 

4. winshark 사용

사용 전에 filter에 rssi >= -70 하면 -70db 이상의 신호만 packet capture한다. 본인의 환경에 맞게 filter를 설정할 수 있다.

nRF Sniffer for Bluetooth LE COM XX 를 선택하고 더블클릭하면 capture를 진행한다.

주변에 BLE 신호가 capture 되는 것을 볼 수 있다.

아.. 내 central / peripheral 장치는 켜지도 않았는데 --;;

 

내 장치만 선택해서 표시할 필요가 있어보인다.

 

그럴때 사용하는게 필터이다.

상단의 창에 btle.advertiing_address == 하고 peripheral 장치의 어드레스를 입력해준다.

그럼 advertising 하고 있는 peripheral 장치 만 capture 한다.

 

일단 나는 속도를 2M로 사용하고 싶어서 시작한 것이었는데 표시된것을 보니 PHY : LE 1M 이다.

펌웨어에서 설정은 2M로 했는데... 뭔가 제대로 동작하지 않는다는 것이다.

 

이부분은 펌웨어를 수정해보기로 하고.

 

사실 Sniffer를 해본 이유는 Peripheral - Central을 연결하고 실제 전송되는 Packet을 분석하고자 함이었는데

sniffer가 그런건 아닌가보다. 연결되면 Capture에 나타나지 않는다.

딱히 암호화한 packet을 쓰지 않았는데 안된다.

이부분은 아직 내가 모르는것일수 있겠다만 여튼 PHY 속도 확인해본것으로 만족해야겠다.

 

sniffer에 대한 부분은 노르딕에서 제공하는 아래 링크에 상세히 나와있다.

 

Nordic Semiconductor Infocenter

 

Nordic Semiconductor Infocenter

 

infocenter.nordicsemi.com

 

요새 엄청 유행? 하고 있는 Stable Diffusion을 한번 해보기로 했다.

하필 가지고 있는 노트북들은 모두 내장그래픽에 CPU도 AMD이고

데스크탑이 그나마 AMD 3600에 Nvidia 1050ti, RAM 32G, SSD 1T 여서 여기다가 한번 해보려고 한다.
* 검색해보니 950ti로도 된다고 하는데 1050ti는 거의 최소사양 이다. 얼마나 걸리는지 궁금하다.

 

일단 나는 관련한 지식이 전혀 없고 호기심에 구글링 해가면서 진행해보려고 한다.

 

1. 우선 파이썬을 설치한다. 아래 링크에서 3.11.3을 설치했다. 

3.11 설치하면 나중에 에러 발생하여 3.11을 지우고 3.10.11을 다시 설치했다.

 

Download Python | Python.org

 

Download Python

The official home of the Python Programming Language

www.python.org

 

2. git을 설치한다. 아래 링크에서 2.40.0 standalone installer 버전으로 설치했다.

Git - Downloading Package (git-scm.com)

 

Git - Downloading Package

Download for Windows Click here to download the latest (2.40.0) 32-bit version of Git for Windows. This is the most recent maintained build. It was released about 1 month ago, on 2023-03-14. Other Git for Windows downloads Standalone Installer 32-bit Git f

git-scm.com

3. stable diffusion webui 설치

git의 설치가 완료되면 cmd로 명령프롬프트 창을 열어서 다운로드할 폴더로 이동한 다음

아래의 명령어로 webui를 다운로드 한다.
git clone https://github.com/AUTOMATIC1111/stable-diffusion-webui.git

 

GitHub - AUTOMATIC1111/stable-diffusion-webui: Stable Diffusion web UI

Stable Diffusion web UI. Contribute to AUTOMATIC1111/stable-diffusion-webui development by creating an account on GitHub.

github.com

아래의 그림처럼 sd라는 폴더를 만들고 거기에 다운로드 했다.

 

stable-diffusion-webui 폴더로 이동하여 webui-user.bat 실행

아.. 그런데 error가 나왔다.

검색해보니 python 3.10 깔란다. 

[Bug]: ERROR: Could not find a version that satisfies the requirement torch==1.13.1+cu117 · Issue #7166 · AUTOMATIC1111/stable-diffusion-webui · GitHub

 

[Bug]: ERROR: Could not find a version that satisfies the requirement torch==1.13.1+cu117 · Issue #7166 · AUTOMATIC1111/stable

Is there an existing issue for this? I have searched the existing issues and checked the recent builds/commits What happened? When I run webui-user.bat I get error: stderr: ERROR: Could not find a ...

github.com

파이썬을 3.10.11을 다시 깔고 python을 찾을수 없다고 나오길래 venv 폴더에 들어가서 pyvenv.cfg 파일을 들어가보니

폴더가 기존의 3.11로 되어있어 새로 설치한 3.10에 맞춰 수정하고 저장했더니 된다.

 

다시 webui-user.bat 실행하니

처음에는 실행시 필요한 파일들 다운로드하느라 엄청 오래걸린다. (10분 넘게 걸린듯하다..)
자동으로 브라우저가 실행될 줄 알고 기다렸는데 메시지 보니 URL: http://127.0.0.1:7860 이 있길래

브라우저에 127.0.0.1:7860 을 치니 실행된다 ㅋ

cmd 명령프롬프트는 그대로 둬야한다.

 

일단 txt2img 에서 prompt에 "pretty girl who playing golf" 로 한번 시도해보았다.

그래픽카드 사용을 꽤 하긴하는데 그래도 잘 된다.

 

결과물은?

 

기본설정을 그대로두고 5번 했는데 한장당 40초 정도 걸리는듯하다.

여튼 결과물은.. 엉망이다 ㅋㅋㅋ

프롬프트도 그렇고 셋팅도 그렇고 좀 더 배워야겠다.

일단 오늘은 셋팅하고 되는거 확인한걸로 만족!

뭐 전자기기에 관심이 있는 사람이면 대부분 2020년에 나온 M1 맥북에 대해 한번쯤은 들어봤을테고

그만큼 관심은 있지 않았을까 싶다.

나라고 뭐 다르겠냐만은 H/W 관련 개발을 하는 업무 특성상 윈도우가 필수이고 10여년전 맥북에어 사서 그다지 큰 이용을 하지 못했던 경험도 있어 여태 주저주저 했었다.

그렇게 2022년이 되고 M2가 나오면 M1은 가격이 저렴해지지 않을까 기대했었건만...

뒤통수를 맞았다. M2가 더 비싸게 나온것은 그러려니 했는데 기존의 M1도 올라버렸다. ㅋㅋㅋ

 

당근마켓에 키워드로 올려뒀었는데 지난주에 관심이 가는 매물이 하나 올라왔다.

M1 RAM 8G, SSD 512G 사용감있슴 가격이 매우 저렴하게 게다가 다음날 거래시 5만원 네고!

이번엔 진짜 사용해볼 요량으로 컨택해보았는데 운좋게 덜컥 구매하게 되었다.

사용감 있다고 했는데 닦으니 기스 하나 없이 깨끗했고 배터리 사이클도 7회 

이자리를 빌어 판매자분께 감사!

 

이런저런 셋팅을 좀 해보고 대략적인 성능이 궁금해서 가지고 있더 아이유 8K 동영상을 INNA로 재생해보았다.

집에 CPU 라이젠 3600, 그래픽 1050ti 인 데스크탑 PC로는 팟플레이어로 시작하자마자 영상도 끊기고 사운드 싱크도 안맞는데

맥북으로 일단 시작도 그럭저럭 하고 시간 좀 지나면 스로틀링으로 끊기긴 하지만 사운드와 싱크는 유지한다.

소음도 없고 발열도 적은데 대비해서 대단한 성능이다. 그리보 배터리 역시 소문대로 정말 오래간다.

 

여튼 이 포스팅도 맥북으로 쓰고 있고 아직 뭐 제대로 쓰고 있진 않지만 이번엔 이것저것 개발용으로 써볼 요량이다.

이 포스팅을 하는김에 생각난게 오래된 노트북이 몇대 있는데 그것도 여기에 기록차원으로 좀 남겨둬야겠다.

필요없는건 처분도 좀 하고.. 처분이 될것 같진 않지만 ㅎ

 

 

2022년 4월 4일 1,000,000원으로 시작 ~ 4월 18일까지 거래하다가 랜섬웨어로 PC들이 맛가서 Stop

2022년 6월 15일 다시 정비해서 재개 그리고 7월 22일까지 총 37 거래일

1,000,000원이 755,581원이 되었다. 약 -24.5% 손실

 

KOSPI가 4월 4일 2757.90 ~ 7월 22일 2393.14로 약 13.2% 빠졌으니 훨씬 안좋은 결과이다.

 

처음 알고리즘으로 운영을 하면서 하한가를 맞는 종목들에 대한 대처가 전혀 안되고 손실로 작동을 해서

Losscut을 그리고 수익률 또한 특정 수익률이 되면 매도처리 하는 함수를 6월 중순경부터 넣어 돌렸으나

손실은 크게 다르지 않았다.

 

7월 중순부터는 그동안 일자별로 매수종목 리스트를 파일로 저장해두었는데

이를 기반으로 시뮬레이션을 돌려 최적의 K값과 이익이 나는 수익률 Cut, 그리고 Loss cut 비율을 찾아보고 적용해보았으나 역시 별 효과는 없었다.

 

       A371160  A271050  A409820  A233740   A390950  
고가      6635.0   4605.0   4860.0   8390.0  100735.0  
저가      6485.0   4540.0   4810.0   8045.0  100715.0  
종가      6485.0   4575.0   4830.0   8240.0  100715.0  
변동폭      150.0     65.0     50.0    345.0      20.0  
09:00   6485.0   4525.0   5000.0   8485.0  100745.0  
09:01   6485.0   4530.0   5010.0   8480.0  100740.0  
09:02   6510.0   4540.0   5010.0   8515.0  100740.0  
09:03   6500.0   4540.0   5000.0   8485.0  100740.0  
09:04   6555.0   4530.0   5015.0   8515.0  100740.0  
09:05   6520.0   4540.0   5005.0   8480.0       0.0  
09:06   6520.0   4535.0   5005.0   8460.0       0.0  
09:07   6515.0   4545.0   5015.0   8455.0  100740.0  
09:08   6515.0   4545.0   5015.0   8445.0       0.0  
09:09   6515.0   4540.0   5015.0   8405.0       0.0  
09:10   6510.0   4545.0   5010.0   8385.0  100740.0  
09:11   6515.0   4545.0   5005.0   8395.0  100740.0  
09:12   6520.0   4550.0   5005.0   8355.0       0.0  
09:13   6520.0   4550.0   5000.0   8345.0       0.0  
09:14   6515.0   4555.0   5000.0   8355.0  100740.0  
09:15   6550.0   4550.0   5000.0   8345.0  100740.0  
09:16   6545.0   4550.0   5000.0   8340.0       0.0  
09:17   6535.0   4550.0   5005.0   8355.0       0.0  
09:18   6535.0   4550.0   5000.0   8375.0       0.0  
09:19   6535.0   4550.0   5000.0   8395.0       0.0  
09:20   6535.0   4550.0   5000.0   8430.0       0.0  
09:21   6535.0   4550.0   5000.0   8415.0       0.0  
09:22   6545.0   4555.0   5010.0   8420.0       0.0  
09:23   6540.0   4550.0   5010.0   8405.0       0.0  
09:24   6530.0   4550.0   5005.0   8410.0       0.0  
09:25   6540.0   4550.0   5010.0   8390.0       0.0  
09:26   6535.0   4550.0   5010.0   8405.0       0.0  
09:27   6530.0   4545.0   5005.0   8410.0       0.0  
09:28   6530.0   4545.0   5010.0   8400.0       0.0  
09:29   6530.0   4550.0   5010.0   8395.0       0.0  
09:30   6530.0   4550.0   5005.0   8360.0  100745.0  
09:31      0.0   4545.0   5010.0   8375.0       0.0  
09:32   6525.0   4555.0   5010.0   8350.0  100740.0  
09:33   6525.0   4570.0   5005.0   8325.0       0.0  
09:34   6520.0   4570.0   5000.0   8320.0       0.0  
09:35   6525.0   4565.0   5005.0   8320.0       0.0  
09:36   6525.0   4565.0   5010.0   8315.0       0.0  
09:37      0.0   4570.0   5005.0   8295.0  100740.0  
09:38   6520.0   4565.0   5005.0   8285.0  100740.0  
09:39      0.0   4575.0   5005.0   8285.0  100740.0  
09:40   6525.0   4575.0   4995.0   8275.0  100740.0  
09:41   6520.0   4570.0   4990.0   8295.0       0.0  
09:42   6530.0   4575.0   4995.0   8320.0  100740.0  
09:43   6520.0   4575.0   4995.0   8320.0  100740.0  
09:44   6520.0   4580.0   4995.0   8315.0  100740.0  
09:45   6520.0   4580.0   4995.0   8295.0  100740.0  
09:46      0.0   4590.0   4995.0   8310.0  100740.0  
09:47   6535.0   4595.0   4995.0   8315.0  100740.0  
09:48   6535.0   4595.0   4995.0   8300.0  100740.0  
09:49      0.0   4595.0   4990.0   8320.0  100740.0  
09:50   6535.0   4595.0   4995.0   8295.0  100740.0  
09:51   6535.0   4590.0   4995.0   8275.0  100740.0  
09:52   6535.0   4590.0   4990.0   8270.0  100740.0  
09:53   6535.0   4590.0   5000.0   8250.0  100740.0  
09:54      0.0   4590.0   4995.0   8255.0  100740.0  
09:55   6530.0   4590.0      0.0   8265.0  100740.0  
09:56   6525.0   4585.0   4995.0   8280.0  100740.0  
09:57   6515.0   4580.0   5000.0   8280.0  100740.0  
09:58      0.0   4580.0   4995.0   8275.0       0.0  
09:59   6520.0   4580.0   4995.0   8260.0       0.0

위와 같이 종목리스트를 기준으로 전날의 변동폭을 pykrx를 이용하여 만들고

당일의 분단위 거래가를 yfinance를 이용하여 구한뒤

dataframe으로 저장

그리고 K값, Profit cut ratio, Loss cut ratio를 for문으로 돌려 가장 이득이 최대, 손실이 최소 인 값을 시뮬레이션 해보았다.

 

여튼 실패. 

시장을 이기긴 힘들다 게다가 어설프면 크게 당한다.

slack으로 매수, 매도 할때 등 메시지를 보냈으므로 그동안 살펴보면

 

자동화 프로그램은 매수시점이 꼭 한발 늦는다. 그래서 비싸게 산다.

그리고 최근의 시장은 조금 올렸다가 금새 내리꽂아 버린다.

이게 느낌적인 느낌일수 있겠지만 여튼 전략을 바꿔서

 

매수종목리스트의 10종목을 9시가 되면 무조건 매수
그리고 수익 또는 손실에 매도 해버리는 더 전략으로 바꿔보려고 한다.

이렇게 또 당분간 돌려보면서 고민해봐야겠다.

수업료는 둘째치고 그만큼 공부는 하고 있나?
그렇지 못한것 같은것도

녹아버린 계좌만큼 씁쓸하다.

 

일단 오늘까지의 파일은 저장! ㅋ (그럴일은 없겠지만 이거 다운받아 쓰시면 계좌가 녹아요~ ㅋㅋ)

 

AutoTrade.py
0.02MB

 

Basler 카메라는 흑백은 둘째치고 비네팅이 생긴다... FOV도 현재 사용하고자 하는 영역과 맞지 않는다.

Application에 맞는 카메라와 렌즈는 딜리버리가 6개월... 이놈의 공급망 문제 ㅠㅜ

 

일단 알고리즘은 계속 진행해야 해서 로지텍 웹캠으로 알고리즘은 진행하기로 하고 적당한 카메라는 계속 고민 중이다.

 

여튼 로지텍 웹캠을 opencv에서 장치를 열때 발생하는 문제에 대해 적어본다.

( 단지 C930C 만의 문제일지 해당하는 모델이 더 있는지는 모르겠다.)

 

기본적으로 opencv에서 장치를 열때

 

cap = cv2.VideoCapture(0)

 

이와 같이 VedeoCapture 함수로 장치를 열고 괄호 안의 장치번호를 이용하는데 현재 노트북을 사용하고 있어서

노트북 기본 카메라가 0번

로지텍 웹캠이 1번이었다.

 

그런데 문제는 cap = cv2.VideoCapture(1) 로 열면 640 * 480 화질로 열리긴 하는데 원래의 해상도인 FULL HD로 설정이 안된다.

 

cap = cv2.VideoCapture(1)

cap.set(cv2.CAP_PROP_FRAME_WIDTH,1920)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT,1080)

여기서 VedeoCapture를 열때 방법이 있다.

아래의 opencv document에 자세히 나와있다.

OpenCV: Flags for video I/O

 

OpenCV: Flags for video I/O

enum  cv::VideoCaptureAPIs {   cv::CAP_ANY = 0,   cv::CAP_VFW = 200,   cv::CAP_V4L = 200,   cv::CAP_V4L2 = CAP_V4L,   cv::CAP_FIREWIRE = 300,   cv::CAP_FIREWARE = CAP_FIREWIRE,   cv::CAP_IEEE1394 = CAP_FIREWIRE,   cv::CAP_DC1394 = CAP_FIRE

docs.opencv.org

 

그래서 아래처럼 해보았더니 바로 열리긴 한다.

cap = cv2.VideoCapture(1,cv2.CAP_DSHOW)
cap.set(cv2.CAP_PROP_FRAME_WIDTH,1920)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT,1080)

해상도도 FULL HD로 설정이 되었다. 문제는 보여지는 화면이 뭔가 끊기는 기분이라 Frame을 계산해서 출력해보았더니...

5FPS... 30FPS이 5FPS로 Frame Drop이 일어났다.

 

뭐 Buffer 셋팅에서부터 별걸 다해보았지만 아무것도 안됨

 

결국 로지텍 웹캠이 지원하는 open 방법이 무엇인지를 찾아보니

cap = cv2.VideoCapture(1,cv2.CAP_DSHOW)

cap = cv2.VideoCapture(1,cv2.CAP_MSMF)

이 두가지 방법이었다.

Direct Show는 Frame Drop 이 있으니 안되고 MSMF로 시도해보았더니 아.. 이 MSMF가 별도의 설정없이 VideoCapture(1) 이것이었다. 이게 아예 안되는 것은 아니었고

열리고 FULL HD로 셋팅은 되는데 시간이 5분가량 걸린다...

이래선 진행을 할 수 가없다. ㅠㅜ

 

열심히 검색한 결과 해결방법을 찾았는데 python 코드 앞머리에서 아래와 같은 설정을 해주어야 한다.

os.environ["OPENCV_VIDEOIO_MSMF_ENABLE_HW_TRANSFORMS"] = "0"
 
 

이것도 주의해야 하는데

 

import os
import cv2
import timeit
import numpy as np
os.environ["OPENCV_VIDEOIO_MSMF_ENABLE_HW_TRANSFORMS"] = "0"
 
이렇게 import의 뒤에 갖다 놓으면 동작 안됨 --;;;
 

 

import os
os.environ["OPENCV_VIDEOIO_MSMF_ENABLE_HW_TRANSFORMS"] = "0"
import cv2
import timeit
import numpy as np
 
이렇게 해야 정상적으로 동작
 
여튼 이 방법으로 로지텍 C930C는 정상적으로 바로 열리고 Frame Drop 없이 FULL-HD 해상도로 설정도 가능하게 되었다.
 
관련 자료가 없어 애먹어서 여기에 남긴다.

정말 오랫동안 건드리지도 않았던 비전 일을 해야할일이 갑자기 생겨버렸다.

 

카메라도 렌즈도 내가 선택안했는데 남이 선택해놓은걸....

 

여튼 Basler 카메라, 리코 12mm c마운트 렌즈, GiGE 인터페이스 이거 달랑 인계 받고 시작하게 되었다.

 

GiGE 인터페이스라고 별다른 것은 없더라 이더넷 케이블로 연결하고 Basler 홈페이지에서 프로그램 다운받은 후

 

pylon viewer 실행 시켜서 보면 보인다.

 

어라.. 근데 흑백이다. 사람에게 보여줄게 아니므로 흑백도 상관없겠다만 프로젝트를 생각하면 컬러가 유리할듯한데...

 

일단 회사에 있는 로지텍 웹캠 C930c를 연결해서 이걸로 진행해보기로 한다.

 

지금까지는 C++ 에 opencv를 사용했는데

 

이번엔 파이썬에 opencv를 사용해보기로 결정

 

1. python 홈페이지에서 파이썬을 다운로드/ 설치  그냥 최신 3.10.4 다운로드 했다.

당연히 환경변수 path에 들어가야 한다.  (설치할때 체크하면 ok)

Download Python | Python.org

 

2. vscode 다운로드/설치

Download Visual Studio Code - Mac, Linux, Windows

 

Download Visual Studio Code - Mac, Linux, Windows

Visual Studio Code is free and available on your favorite platform - Linux, macOS, and Windows. Download Visual Studio Code to experience a redefined code editor, optimized for building and debugging modern web and cloud applications.

code.visualstudio.com

 

3. 폴더 하나 만들고 그 안에서 작업

 

일단 vscode 실행시키고 터미널에서 

pip install opencv-python 

하면 opencv가 깔린다. 세상 편하다.. 

이게 뭐 문제점은 없는지 걱정이다 ㅋㅋㅋ

 

여튼 비전이 내 전공도 아니고 까먹을까봐 여기에 기록해가면서 또 진행해보려고 한다.

 

주식자동화 그것도 해야하는데... 귀찮네 ㅠㅜ

 

지난 5년간 너무 고생하셨습니다.

 

고맙습니다.

'끄적:Scrawl > 일상:Ordinary' 카테고리의 다른 글

나의 첫조카  (0) 2013.09.21
Shenzen, China  (0) 2013.07.19
재웅이 결혼  (2) 2012.12.26
끄적  (0) 2012.12.20
자연의 힘?!  (0) 2012.11.07

사실 사건이 발생한지는 시간이 좀 지났다.

고쳐놓은 프로그램이 잘 동작하는지 여부등의 확인을 위해 공유기의 외부접속포트를 열어놓았다.
프로그램이 돌아가고 있는 상태에서 로그등을 봐야하니 아무래도 회사에서 일하고 있는 시간이라

회사에서 접속해서 볼 요량이었다.

 

그리고 그 주 목요일 4/14일은 외근이 있어 나갔다가 집에 와서 컴을 켜보니....

랜섬웨어 경고창이... ㅠㅠ

 

맘이 급해 캡춰나 사진을 찍을 생각은 당연히 못하고

랜선뽑고 물려있는 외장하드들 떼어내고, 다른 PC와 NAS의 모든 LAN 연결 뽑았다.

하필이면 주식 PC가 저녁에 유튜브도 보고 영상도 보는 PC라 내장하드, 외장하드 많이 연결되어 있는...

 

여튼 다음과 같은 랜섬웨어에 감염되었다.

Elbie 랜섬웨어를 제거하고 .Elbie 파일을 해독하는 방법 (free-uninstall.org)

 

위 이미지는 위 링크에서 가져왔고 위 링크에 잘 설명되어 있다.

(여기에 보면 원격접속프로토콜 RDP 로 타고들어오니 접속포트 변경하라 라고 나와있는데...  지금생각해보니 너무 당연한건데... 내가 너무 안일했다 ㅠㅜ)


증상은 파일들이 *.Elbie 로 바뀌어버렸고

윈도우디펜더는 사라져서 무용지물이 되었고

내장하드 2개, 외장하드 2개 중 1개 감염

네트워크드라이브로 연결해둔 NAS 감염

C드라이브에 있던 주식 자동투자 관련 소스도 감염...

방법이 없다. 모두 포맷하는것 외엔 ㅠㅜ
그나마 NAS와 같이 윈도우즈 시스템 밖에 있는 데이터는 .Elbie 파일들을 제거하는 것만으로 별문제 없이 해결이 되었지만 불안해서 NAS도 시놀로지 다시 깔고

PC와 HDD는 모두 포맷 


일단 그렇게 시스템을 재정비하고

백업 관련해서는 어떻게 하면 좋을지 구상하고 있다.

의욕이 많이 꺾여버렸다..

아~ 잔인한 4월이여~

알리에서 진공관 Pre-amp와 Power-Amp가 도착했다.

그리고 국내에서 구매한 삼미의 풀레인지는 진즉 도착했고

곧이어 1인치 트위터도 도착했다.

 

연결해서 테스트해봐야 하는데 이게 왜이리 귀찮은지 하루이틀 미루다 이제야 테스트 해보게 되었다.

 

아... 스피커 한쪽이 안나온다. 

테스트 결과 Power-Amp로 구매한 TPA3116 앰프가 불량... 알리산이 글치 

접점불량이나 납땜불량 여부정도 확인해보았으나 아니었다.

 

그리고 스피커도 하나가 배송중 파손으로 치직거린다.

 

이걸 영상으로 촬영했는데 습관적으로 아이유 노래를 틀고 녹화시켜서 저작권 생각해서 일부만 잘라냈다. ㅋ

 

 

한쪽은 잘 나온다 ㅋ

 

* 이 작업은 사실 3월 1일에 했고 스피커 한쪽은 교환 받았고,

앰프는 알리에서 TPA7297 이라는 15W 앰프와 TPA3116 다른 버전의 앰프를  주문해서 이미 받았다 ㅋ

둘 중에 더 맘에 드는 놈으로 진행할 예정 

 

 

'Study 외 > DIY' 카테고리의 다른 글

[진공관 올인원 오디오 DIY] #1 - 기획?  (0) 2022.02.28

지난번 포스팅에서

Creon Plus 연결할때 키보드 연결 어쩌구 오류가 나왔었다고 썼는데 이는 PC를 사용할때는 나오지 않는 문제점인데 

밤새 사용하지 않다가 아침에 Creon Plus 자동실행하면 Ahnlab Online Security 에서 띄우는 문제점인가 보다.
여튼 아래와 같은 메시지가 뜨는데 파이썬으로 자동으로 Enter가 입력되게 해보려했으나 실패했다.

일단 출근전에 수동으로 Enter 한번 눌러주면 되긴 하니까 당분간은 그렇게.. T.T

 

 

4월 4일 월요일 첫날 성적은 좋았다. 수익률은 3.66% 문제점이라고 하긴 뭐하고 개선점으로 생각되는 부분이 보였다.

전 영업일에 자동으로 리스트업 해둔 리스트 중 3종목을 자동으로 매매를 했는데 그중 한 종목이 오전중 상한가를 쳤다.

알고리즘으로는 5종목까지 매수할수 있도록 예수금의 19%만 매수되게 했기에 상한을 쳐도 전체수익률이 상한은 아니다.

여튼 오전에 상한을 쳤으나 장종료 직전 매도까지 그상태 그대로 있다가 매도를 하게 된다.

이를 대비해서 상한에 근접 또는 상한가를 치면 바로 매도를 하도록 그리고 유리한 가격에 매도를 하도록 하는게 좋겠다.

 

 

4월 5일 둘째날은 안좋다. -1.22%

4개의 종목이 자동투자 되었는데 1개의 종목이 하한가에 근접했다. 이는 확실히 문제점이 맞다.

이부분 역시 대비해서 매수후 일정 % 이하로 떨어지면 손절을 하도록 프로그램을 수정하도록 해야겠다.

 

첫번째 문제건 두번째 문제건 팔아야한다.

 

주기적으로 체크해서 특정 이상 손실이면 팔고, 특정 이상 수익이면 팔아버리자

def check_losscut(code):
    try:
        global bought_list      # 함수 내에서 값 변경을 하기 위해 global로 지정
        time_now = datetime.now()
        cur_price, ask_price, bid_price = get_current_price(code) 
        bought_price_index = bought_list.index(code)
        bought_price = bought_list_price(bought_price_index)
        price_ratio = ((cur_price - bought_price)/cur_price)*100.0
        if price_ratio < -5.0:      #losscut -5%
            dbgout("-5% 이하로 떨어져서 손절 절차에 들어갑니다." + str(code))
            sell_stock(code)

        if price_ratio > 28.0:     #상한가
            dbgout("상한으로 판단하여 매도 절차에 들어갑니다." + str(code))
            sell_stock(code)

    except Exception as ex:
        dbgout("check_losscus() -> exception! " + str(ex))

뭐 이름을 losscut으로 했지만 수익이 나도 파는 것으로 했다.

기본적인 알고리즘은 샀을때 가격을 list에 넣어두었고 이를 현재가와 비교해서 

-5% 손실이면 손절

+28% 수익이면 상한으로 간주하고 익절하도록 했다.

 

돌아갈지는 아직 모르겠다 ㅎ

 

 

일단 실제 거래가 되는 루틴은 막고 돌려보았다.

 

3월 31일

오전 8시 Creon Plus 자동연결은 알아서 실행되었으나

Creon Plus 연결할때 키보드 연결 어쩌구 오류가 나왔는데 확인 누르니 넘어가고 

 

자동거래프로그램도 자동으로 실행되었는데... 퇴근하고 보니

아... 아무런 기록도 남아있지 않았다.

 

그리고 매수종목 리스트 프로그램도 실행결과가 남아있질 않았다.

 

자 하나씩 해결해보자.

1. 일단 Print 로그를 파일로 저장해버리기 위해 기존의 .py 를 실행하는 방식이 아닌 .bat 파일 실행 방식으로 바꾸었다.

 

AutoTrade.bat 파일을 만들고 파일의 내용은

python AutoTrade.py > AutoTradeResult.txt

이런식으로 저장해두고 작업 스케줄러를 다음과 같이 수정해서 bat파일을 실행하게 해주었다.

매수종목 list 만드는 프로그램도 마찬가지로 작업해서 txt파일로 기록을 남겨두도록 하였다.

 

2. Slack으로 메시지를 보내도록 수정했다.

프로그램의 시작/종료, 매수를 알리는 일 등을 Slack으로 메시지를 보내도록 수정하였다.

 

3. 매수종목 list 만드는 프로그램의 오류 수정

매수종목 list 만드는 프로그램이 결과를 내지 못하는 이유를 디버깅 하다보니 중간에 어제날짜의 데이터가 없으면 Error가 나는 것이었다. 그래서 DataFrame의 행의 수를 살펴 어제와 오늘 날짜의 Data가 있는 경우만 진행하도록 수정했다.

df = stock.get_market_ohlcv_by_date(fromdate=by_day, todate=bt_day, ticker=etf_ticker)
    if(len(df) == 2):

수정한 source

from pykrx import stock
import time,sys
import pandas as pd
from datetime import datetime,timedelta
import requests

def post_message(token, channel, text):
    response = requests.post("https://slack.com/api/chat.postMessage",
        headers={"Authorization": "Bearer "+token},
        data={"channel": channel,"text": text}
    )
    print(response)

myToken = "xoxb-2241580444021-2948023303025-K4NHATNUlfFIJzl6KIpkhd9u"
def dbgout(message):
    """인자로 받은 문자열을 파이썬 셸과 슬랙으로 동시에 출력한다."""
    print(datetime.now().strftime('[%m/%d %H:%M:%S]'), message)
    strbuf = datetime.now().strftime('[%m/%d %H:%M:%S] ') + message
    #slack.chat.post_message('#etf-algo-trading', strbuf)
    post_message(myToken,"#stock",strbuf) 

dbgout('매수종목 List 작성을 시작합니다.')
#DataFrame define
kospi_stock_list = pd.DataFrame(columns=['stock_code','price','yesterday_volume','today_volume','volume_ratio'])
kosdaq_stock_list = pd.DataFrame(columns=['stock_code','price','yesterday_volume','today_volume','volume_ratio'])
etf_stock_list = pd.DataFrame(columns=['stock_code','price','yesterday_volume','today_volume','volume_ratio'])

today = datetime.today()- timedelta(0)      #오늘날짜 구하기 timedelta(1)을 빼면 어제날짜
yesterday = datetime.today()- timedelta(1)
str_today = today.strftime("%Y%m%d")        #구한 날짜를 String type으로
str_yesterday = yesterday.strftime("%Y%m%d")        #구한 날짜를 String type으로

print(str_today)
print(str_yesterday)
bt_day = stock.get_nearest_business_day_in_a_week(date=str_today)   #오늘 날짜 집어넣고 장을 여는 가장 가까운 날을 구함 오늘 장을 열면 오늘 날짜 반환
by_day = stock.get_nearest_business_day_in_a_week(date=str_yesterday)
print("btday=",bt_day)
print("byday=",by_day)
if bt_day != str_today: #오늘 날짜와 구한 날짜가 같지 않다는건 오늘 장을 열지 않는다는 것
    print("오늘은 장을 열지 않으므로 프로그램 종료")
    sys.exit(0)

kospilist = stock.get_market_ticker_list(date=bt_day, market="KOSPI")   #KOSPI 종목코드를 list로 반환
kosdaqlist = stock.get_market_ticker_list(date=bt_day, market="KOSDAQ") #KOSDAQ 종목코드를 list로 반환
etflist = stock.get_etf_ticker_list(date=bt_day)                        #ETF 종목코드를 list로 반환

kospi_stock_list_count = 0      #나중에 Dataframe에 count로 사용할 변수 초기화
kosdaq_stock_list_count = 0
etf_stock_list_count = 0

print("KOSPI 확인 - 종목수 : ",len(kospilist))
for kospi_ticker in kospilist:  #KOSPI 종목
#for i in range(100):   #for test
    #kospi_ticker = kospilist[i]    #for test
    df = stock.get_market_ohlcv_by_date(fromdate=by_day, todate=bt_day, ticker=kospi_ticker)    #KOSPI 종목코드 어제,오늘 관련정보 DataFrame

    if(len(df) == 2):
        yesterday_volume = df.iloc[0]['거래량']     #DataFrame에서 어제 거래량 변수로 입력
        today_volume = df.iloc[1]['거래량']         #DataFrame에서 오늘 거래량 변수로 입력
        today_price = df.iloc[1]['종가']            #DataFrame에서 오늘 종가 변수로 입력
        
        print("종목코드",kospi_ticker)
        print("종가",today_price) 
        print("어제 거래량",yesterday_volume)
        print("오늘 거래량", today_volume)
        if yesterday_volume == 0:                   #어제거래량이 없으면 거래량변화 -100
            volume_ratio = -100
        else:
            volume_ratio = (today_volume-yesterday_volume)/yesterday_volume     #거래량변화율 

        
        new_data = [kospi_ticker,today_price,yesterday_volume,today_volume,volume_ratio]
        kospi_stock_list.loc[kospi_stock_list_count] = new_data     #관련 정보 DataFrame의 행에 추가
        kospi_stock_list_count = kospi_stock_list_count + 1
        time.sleep(1) 

print("KOSDAQ 확인 - 종목수 : ",len(kosdaqlist))
for kosdaq_ticker in kosdaqlist:
#for i in range(100):       #for test
    #kosdaq_ticker = kosdaqlist[i]  #for test
    df = stock.get_market_ohlcv_by_date(fromdate=by_day, todate=bt_day, ticker=kosdaq_ticker)
    if(len(df) == 2):
        yesterday_volume = df.iloc[0]['거래량']
        today_volume = df.iloc[1]['거래량']
        today_price = df.iloc[1]['종가']
    
        print("종목코드",kosdaq_ticker)
        print("종가",today_price) 
        print("어제 거래량",yesterday_volume)
        print("오늘 거래량", today_volume)
        if yesterday_volume == 0:
            volume_ratio = -100
        else:
            volume_ratio = (today_volume-yesterday_volume)/yesterday_volume

        
        new_data = [kosdaq_ticker,today_price,yesterday_volume,today_volume,volume_ratio]
        kosdaq_stock_list.loc[kosdaq_stock_list_count] = new_data
        kosdaq_stock_list_count = kosdaq_stock_list_count + 1
    time.sleep(1) 



print("ETF 확인 - 종목수 : ",len(etflist))
for etf_ticker in etflist:
#for i in range(100):   #for test
    #etf_ticker = etflist[i]    #for test
    df = stock.get_market_ohlcv_by_date(fromdate=by_day, todate=bt_day, ticker=etf_ticker)
    if(len(df) == 2):
        yesterday_volume = df.iloc[0]['거래량']
        today_volume = df.iloc[1]['거래량']
        today_price = df.iloc[1]['종가']
        
        print("종목코드",etf_ticker)
        print("종가",today_price) 
        print("어제 거래량",yesterday_volume)
        print("오늘 거래량", today_volume)
        if yesterday_volume == 0:
            volume_ratio = -100
        else:
            volume_ratio = (today_volume-yesterday_volume)/yesterday_volume

        
        new_data = [etf_ticker,today_price,yesterday_volume,today_volume,volume_ratio]
        etf_stock_list.loc[etf_stock_list_count] = new_data
        etf_stock_list_count = etf_stock_list_count + 1
        time.sleep(1) 

all_stock_list = pd.concat([kospi_stock_list,kosdaq_stock_list])    #KOSPI와 KOSDAQ은 합쳐서 하나의 DataFrame으로

print("KOSPI")
print(kospi_stock_list)
print("KOSDAQ")
print(kosdaq_stock_list)
print("KOSPI+KOSDAQ")
print(all_stock_list)
print("ETF")
print(etf_stock_list)


all_stock_list.sort_values(['today_volume'],axis=0,ascending=False,inplace=True)    #거래량 우선으로 정렬
sort_volume_list = all_stock_list.head(12)                                          #그중 12개만 추출해서 저장
print("all stock sort by volume")
print(sort_volume_list)
sort_volume_list.sort_values(['volume_ratio'],axis=0,ascending=False,inplace=True)  #12개를 거래량 변화율로 정렬
sort_ratio_list = sort_volume_list.head(6)                                          #그 중 6개만 추출해서 저장
print("all stock sort by volume")
print(sort_ratio_list)

etf_stock_list.sort_values(['today_volume'],axis=0,ascending=False,inplace=True)    #ETF도 같은 과정 
etf_sort_volume_list = etf_stock_list.head(28)
print("ETF stock sort by volume")
print(etf_sort_volume_list)
etf_sort_volume_list.sort_values(['volume_ratio'],axis=0,ascending=False,inplace=True)
etf_sort_ratio_list = etf_sort_volume_list.head(14)             
print("ETF stock sort by volume")
print(etf_sort_ratio_list)

total_stock_list = pd.concat([sort_ratio_list,etf_sort_ratio_list])     #최종 KOSPI,KOSDAQ에서 6개, ETF에서 14개 총 20개 를 하나의 DataFrame으로 합치고
print("Total stock sort by volume")
print(total_stock_list)

final_stock_list = list(total_stock_list['stock_code'])     #DataFrame에서 종목코드만 List로 뽑고
print("final Stock List")
print(final_stock_list)

for i in range(len(final_stock_list)):
    final_stock_list[i] = 'A'+ str(final_stock_list[i])     #List에 'A' 추가해서
print(final_stock_list)

f = open('codelist.txt','w')
f.write(','.join(final_stock_list))     #파일로 저장
f.close()

dbgout('매수종목 List 작성을 종료합니다.')
#symbol_list = open('codelist.txt','r').read().split(',')       #for verify
#print(symbol_list)                                             #for verify

 

4월 1일

오전 8시 Creon Plus 자동연결은 알아서 실행되었으나

Creon Plus 연결할때 키보드 연결 어쩌구 오류가 또 나왔는데 역시 확인 누르니 넘어갔다.

나중에 다시 실행해보아도 이부분은 문제가 없이 잘 실행되는데 물리적키보드가 연결이 안되어있는게 문제인건가?

 

그리고 나머지는 잘 실행되긴 했다.

하지만 결과는...

 

일단 실제 프로그래그램에서 매수할 종목의 수는 5종목이지만 실제 매수는 하지 않았으므로 조건에 해당하면 메시지를 보냈다.

그 결과 오늘은 총 7종목이 조건에 해당한다고 메시지를 보냈다.

 

KODEX 인버스(A114800) 0.0EA : 4310 meets the buy condition!`
[04/01 09:10:07] but_etf 매수 종목 : KODEX 인버스종목코드 : A114800현재가 : 4310 => 4300

[04/01 09:10:41] KODEX 200선물인버스2X(A252670) 0.0EA : 2480 meets the buy condition!`
[04/01 09:10:41] but_etf 매수 종목 : KODEX 200선물인버스2X종목코드 : A252670현재가 : 2480 =>2465

[04/01 09:11:38] TIGER 200선물인버스2X(A252710) 0.0EA : 2590 meets the buy condition!`
[04/01 09:11:38] but_etf 매수 종목 : TIGER 200선물인버스2X종목코드 : A252710현재가 : 2590 => 2575

[04/01 09:12:32] TIGER 단기통안채(A157450) 0.0EA : 100740 meets the buy condition!`
[04/01 09:12:32] but_etf 매수 종목 : TIGER 단기통안채종목코드 : A157450현재가 : 100740 => 100730

[04/01 09:23:58] 켐온(A217600) 0.0EA : 3180 meets the buy condition!`
[04/01 09:23:58] but_etf 매수 종목 : 켐온종목코드 : A217600현재가 : 3180 => 2985

[04/01 09:30:06] TJ미디어(A032540) 0.0EA : 9700 meets the buy condition!`
[04/01 09:30:06] but_etf 매수 종목 : TJ미디어종목코드 : A032540현재가 : 9700 => 9400

[04/01 11:20:10] TIGER 차이나전기차SOLACTIVE(A371460) 0.0EA : 14750 meets the buy condition!`
[04/01 11:20:10] but_etf 매수 종목 : TIGER 차이나전기차SOLACTIVE종목코드 : A371460현재가 : 14750 => 14670

 

파란색 글자는 실제 오늘 종가이다.  모두 마이너스 ...

계산해보면 실제 공식보다 비싼 현재가에서 구매를 하는걸로 되는데 이부분 감안해서 K값을 조금 줄여야 할것 같다.

현재 K값은 0.5

여튼 실제 투자는 다음주부터 일단 해보는 걸로!

 

 

책을 아직도 다 읽진 않았지만 - 앞으로도 다 읽진 않겠지만 - 

매수종목 선정 방법 관련해서는 자세히 나온것이 없다. 

그래서 임의로 내가 방법을 세우고 프로그래밍해려고 한다.

 

검색해보면 이러한 종목이 오를 것이다라는 여러 이야기 들이 있지만 복잡한것까지는 잘 모르겠다.

내 경험상으로도 그렇고 검색 결과로도 그렇고 일단 거래량이 가장 중요한 것 같다.

그래서 일단 단순하게

 

1. 이틀전 거래량 - 하루전 거래량 으로 거래량 증가폭이 높은 순으로 정렬해서 최상단 20종목 추리고

2. 그중 하루전 거래량 기준으로 절대 거래량 높은 순으로 10종목 추려서 매수종목 리스트에 넣는다.

 

이런 단순한 방법을 우선 취해보기로 했다. 

이렇게 한 근거는 일단 없다. 이렇게 해보고 결과가 안좋으면 수정해야겠다.

 

크레온 플러스 API 예제를 이용하면 더 편할것 같기도 한데 이게 제한이 있다.

   조회 제한  실시간 제한
시세
오브젝트
15초에 최대 60건으로제한
초과 요청시 첫 요청으로부터 15초가
지날 때까지 내부적으로기다림
최대 400건의요청으로제한
초과요청시오류
주문관련오브젝트 15초에 최대 20건으로제한
초과 요청시 첫 요청으로부터 15초가
지날 때까지 요청함수(Request, BlockRequest, BlockRequest2)에서
4를 반환
제한 없음

그래서 일단 네이버 스크래핑을 위주로 이용해보기로 한다.

 

먼저 처음 예제였던 종목정보 구하기 예제를 차후에 파일로 가공할 것을 감안하여 조금 수정하고

실행해서 전체종목의 코드를 구해봤다. (이건 크레온 플러스 API 이용)

 

import win32com.client

# 연결 여부 체크
objCpCybos = win32com.client.Dispatch("CpUtil.CpCybos")
bConnect = objCpCybos.IsConnect
if (bConnect == 0):
    print("PLUS가 정상적으로 연결되지 않음. ")
    exit()
 
# 종목코드 리스트 구하기
objCpCodeMgr = win32com.client.Dispatch("CpUtil.CpCodeMgr")
codeList = objCpCodeMgr.GetStockListByMarket(1) #거래소
codeList2 = objCpCodeMgr.GetStockListByMarket(2) #코스닥
 
 
print("번호",",","종목코드",",","종목명",",","구분코드",",","금액")
for i, code in enumerate(codeList):
    secondCode = objCpCodeMgr.GetStockSectionKind(code)
    name = objCpCodeMgr.CodeToName(code)
    stdPrice = objCpCodeMgr.GetStockStdPrice(code)
    print(i,",",code,",", name,",", secondCode,",", stdPrice)
    
for i, code in enumerate(codeList2):
    secondCode = objCpCodeMgr.GetStockSectionKind(code)
    name = objCpCodeMgr.CodeToName(code)
    stdPrice = objCpCodeMgr.GetStockStdPrice(code)
    print(i+len(codeList),",",code,",", name,",", secondCode,",", stdPrice)
 
#print("거래소 + 코스닥 종목코드 ",len(codeList) + len(codeList2))

실행할 때 단지 아래와 같이 하면 print 결과값을 파일로 저장한다.

python test1.py > codelist.txt

 

이로써 codelist.txt라는 종목정보파일이 만들어졌다.

이 파일의 끝을 보면 "거래소 + 코스닥 종목코드  3306" 으로 총 3306 종목이 있슴을 알 수 있고

위 그림과 같이 ETF도 포함되어 있슴을 알 수 있다. 

 

이 txt파일을 엑셀에서 읽어서 금일거래량, 전일거래량, 거래량증가비 열을 추가하고 codelist.xlsx 로 저장했다.

 

우선 파이썬에서 엑셀 데이터를 다루기 위해서 openpyxl을 설치해주도록 한다.

pip install openpyxl을 cmd 창에서 실행

 

 

-----------------------------------------------------------------------------------------------------------------------------------

이렇게 하다가 문제가 발생했다.

여튼 엑셀데이터의 종목코드를 읽고 거래량을 구하는 과정에서 현재 거래정지된 종목의 경우 에러가 발생하는 것이었다.

여기서 예외처리를 할까 하다가 전면 수정을 하기로 하고 다시 프로그램을 작성했다.

종목코드 자체를 매일 실시간으로 읽어서 진행하기로...

 

검색해보니 pykrx 라고 주식관련 라이브러리가 아주 잘되어 있었고 어차피  엑셀을 이용해도 이 라이브러리를 이용했어야 했다. ("GitHub - sharebook-kr/pykrx: KRX 주식 정보 스크래핑" 참고)

 

기본적인 구상은 다음과 같다.

매일 장을 종료하면 이 프로그램을 실행하여

1. 종목코드를 get_market_ticker_list() 로 읽어와서

2. get_market_ohlcv_by_date() 로 거래량 정보를 읽고 가공 후 DataFrame에 집어넣고

3. 각 DataFrame을 거래량 별로 정렬 후 상위 추출, 거래량 변화율 별로 정렬 후 상위 추출

4. ETF는 70%, KOSPI/KOSDAQ에서는 30%로 구성해서 20개 종목을 최종 List 만들어서

5. 파일로 저장

6. 다음날 자동거래 프로그램에서 매수대상 리스트는 이 파일을 읽어서 20개의 후보군으로 실행

 

파이썬을 잘 모르기도 하고 혼자서 단순하게 막 짜다보니 좀 비효율적인 프로그램이 된것 같긴 하지만 일단 테스트로 돌려본 결과 잘 돌아가긴 한다.

 

내일 자동거래 프로그램을 백테스팅용으로 수정을 좀 하고 목,금 백테스팅을 좀 하고 4월부터는 실제거래를 해봐야겠다.

 

 

from pykrx import stock
import time,sys
import pandas as pd
from datetime import datetime,timedelta

#DataFrame define
kospi_stock_list = pd.DataFrame(columns=['stock_code','price','yesterday_volume','today_volume','volume_ratio'])
kosdaq_stock_list = pd.DataFrame(columns=['stock_code','price','yesterday_volume','today_volume','volume_ratio'])
etf_stock_list = pd.DataFrame(columns=['stock_code','price','yesterday_volume','today_volume','volume_ratio'])

today = datetime.today()- timedelta(0)      #오늘날짜 구하기 timedelta(1)을 빼면 어제날짜
yesterday = datetime.today()- timedelta(1)
str_today = today.strftime("%Y%m%d")        #구한 날짜를 String type으로
str_yesterday = yesterday.strftime("%Y%m%d")        #구한 날짜를 String type으로

print(str_today)
print(str_yesterday)
bt_day = stock.get_nearest_business_day_in_a_week(date=str_today)   #오늘 날짜 집어넣고 장을 여는 가장 가까운 날을 구함 오늘 장을 열면 오늘 날짜 반환
by_day = stock.get_nearest_business_day_in_a_week(date=str_yesterday)
print("btday=",bt_day)
print("byday=",by_day)
if bt_day != str_today: #오늘 날짜와 구한 날짜가 같지 않다는건 오늘 장을 열지 않는다는 것
    print("오늘은 장을 열지 않으므로 프로그램 종료")
    sys.exit(0)

kospilist = stock.get_market_ticker_list(date=bt_day, market="KOSPI")   #KOSPI 종목코드를 list로 반환
kosdaqlist = stock.get_market_ticker_list(date=bt_day, market="KOSDAQ") #KOSDAQ 종목코드를 list로 반환
etflist = stock.get_etf_ticker_list(date=bt_day)                        #ETF 종목코드를 list로 반환

kospi_stock_list_count = 0      #나중에 Dataframe에 count로 사용할 변수 초기화
kosdaq_stock_list_count = 0
etf_stock_list_count = 0

print("KOSPI 확인 - 종목수 : ",len(kospilist))
for kospi_ticker in kospilist:  #KOSPI 종목
#for i in range(100):   #for test
#    kospi_ticker = kospilist[i]    #for test
    df = stock.get_market_ohlcv_by_date(fromdate=by_day, todate=bt_day, ticker=kospi_ticker)    #KOSPI 종목코드 어제,오늘 관련정보 DataFrame

    yesterday_volume = df.iloc[0]['거래량']     #DataFrame에서 어제 거래량 변수로 입력
    today_volume = df.iloc[1]['거래량']         #DataFrame에서 오늘 거래량 변수로 입력
    today_price = df.iloc[1]['종가']            #DataFrame에서 오늘 종가 변수로 입력
    
    print("종목코드",kospi_ticker)
    print("종가",today_price) 
    print("어제 거래량",yesterday_volume)
    print("오늘 거래량", today_volume)
    if yesterday_volume == 0:                   #어제거래량이 없으면 거래량변화 -100
        volume_ratio = -100
    else:
        volume_ratio = (today_volume-yesterday_volume)/yesterday_volume     #거래량변화율 

    
    new_data = [kospi_ticker,today_price,yesterday_volume,today_volume,volume_ratio]
    kospi_stock_list.loc[kospi_stock_list_count] = new_data     #관련 정보 DataFrame의 행에 추가
    kospi_stock_list_count = kospi_stock_list_count + 1
    time.sleep(1) 

print("KOSDAQ 확인 - 종목수 : ",len(kosdaqlist))
for kosdaq_ticker in kosdaqlist:
#for i in range(100):       #for test
    #kosdaq_ticker = kosdaqlist[i]  #for test
    df = stock.get_market_ohlcv_by_date(fromdate=by_day, todate=bt_day, ticker=kosdaq_ticker)
    
    yesterday_volume = df.iloc[0]['거래량']
    today_volume = df.iloc[1]['거래량']
    today_price = df.iloc[1]['종가']
    
    print("종목코드",kosdaq_ticker)
    print("종가",today_price) 
    print("어제 거래량",yesterday_volume)
    print("오늘 거래량", today_volume)
    if yesterday_volume == 0:
        volume_ratio = -100
    else:
        volume_ratio = (today_volume-yesterday_volume)/yesterday_volume

    
    new_data = [kosdaq_ticker,today_price,yesterday_volume,today_volume,volume_ratio]
    kosdaq_stock_list.loc[kosdaq_stock_list_count] = new_data
    kosdaq_stock_list_count = kosdaq_stock_list_count + 1
    time.sleep(1) 



print("ETF 확인 - 종목수 : ",len(etflist))
for etf_ticker in etflist:
#for i in range(100):   #for test
    #etf_ticker = etflist[i]    #for test
    df = stock.get_market_ohlcv_by_date(fromdate=by_day, todate=bt_day, ticker=etf_ticker)
    
    yesterday_volume = df.iloc[0]['거래량']
    today_volume = df.iloc[1]['거래량']
    today_price = df.iloc[1]['종가']
    
    print("종목코드",etf_ticker)
    print("종가",today_price) 
    print("어제 거래량",yesterday_volume)
    print("오늘 거래량", today_volume)
    if yesterday_volume == 0:
        volume_ratio = -100
    else:
        volume_ratio = (today_volume-yesterday_volume)/yesterday_volume

    
    new_data = [etf_ticker,today_price,yesterday_volume,today_volume,volume_ratio]
    etf_stock_list.loc[etf_stock_list_count] = new_data
    etf_stock_list_count = etf_stock_list_count + 1
    time.sleep(1) 

all_stock_list = pd.concat([kospi_stock_list,kosdaq_stock_list])    #KOSPI와 KOSDAQ은 합쳐서 하나의 DataFrame으로

print("KOSPI")
print(kospi_stock_list)
print("KOSDAQ")
print(kosdaq_stock_list)
print("KOSPI+KOSDAQ")
print(all_stock_list)
print("ETF")
print(etf_stock_list)


all_stock_list.sort_values(['today_volume'],axis=0,ascending=False,inplace=True)    #거래량 우선으로 정렬
sort_volume_list = all_stock_list.head(12)                                          #그중 12개만 추출해서 저장
print("all stock sort by volume")
print(sort_volume_list)
sort_volume_list.sort_values(['volume_ratio'],axis=0,ascending=False,inplace=True)  #12개를 거래량 변화율로 정렬
sort_ratio_list = sort_volume_list.head(6)                                          #그 중 6개만 추출해서 저장
print("all stock sort by volume")
print(sort_ratio_list)

etf_stock_list.sort_values(['today_volume'],axis=0,ascending=False,inplace=True)    #ETF도 같은 과정 
etf_sort_volume_list = etf_stock_list.head(28)
print("ETF stock sort by volume")
print(etf_sort_volume_list)
etf_sort_volume_list.sort_values(['volume_ratio'],axis=0,ascending=False,inplace=True)
etf_sort_ratio_list = etf_sort_volume_list.head(14)             
print("ETF stock sort by volume")
print(etf_sort_ratio_list)

total_stock_list = pd.concat([sort_ratio_list,etf_sort_ratio_list])     #최종 KOSPI,KOSDAQ에서 6개, ETF에서 14개 총 20개 를 하나의 DataFrame으로 합치고
print("Total stock sort by volume")
print(total_stock_list)

final_stock_list = list(total_stock_list['stock_code'])     #DataFrame에서 종목코드만 List로 뽑고
print("final Stock List")
print(final_stock_list)

for i in range(len(final_stock_list)):
    final_stock_list[i] = 'A'+ str(final_stock_list[i])     #List에 'A' 추가해서
print(final_stock_list)

f = open('codelist.txt','w')
f.write(','.join(final_stock_list))     #파일로 저장
f.close()

#symbol_list = open('codelist.txt','r').read().split(',')       #for verify
#print(symbol_list)                                             #for verify

우연히 알리익스프레스에서 $13 정도하는 저렴한 진공관 프리앰프가 올라온걸 보았다.

AIYIMA 업그레이드된 6K4 튜브 프리 앰프, HiFi, 바일 버퍼, 오디오 앰프, 스피커, 사운드, 홈 시어터, DIY|Amplifier| - AliExpress

 

16163.0₩ 28% OFF|AIYIMA 업그레이드된 6K4 튜브 프리 앰프, HiFi, 바일 버퍼, 오디오 앰프, 스피커, 사운

Smarter Shopping, Better Living! Aliexpress.com

ko.aliexpress.com

진공관 앰프라고 하면 예전부터 가지고 싶었으나 가지지 못한 아니 가지지 않았다고 해야하나? 여튼 계륵같은 존재였다.

그런데 가격이 저렇다면 장난감으로라도 사보는거지 뭐 ㅎㅎㅎ
우리 인생이 그런거지 일단 사고, 용도는 그 다음에 만들어 나가는거 ㅋ
그래서 일단 주문을 했고 배송이 오는 사이에 고민을 했다. 이걸로 뭘하지?

여튼 Pre-Amp니 Power-Amp가 필요했다. 그래서 알리를 조금 검색해보니 아래의 앰프가 저렴하고 평이 좋았다.

 

AIYIMA TPA3116 전력 증폭기 오디오 보드 TPA3116D2 사운드 앰프 2.0 스테레오 스피커 Amplificador 2x120W DIY 홈 오디오|Amplifier| - AliExpress

 

14177.0₩ 28% OFF|AIYIMA TPA3116 전력 증폭기 오디오 보드 TPA3116D2 사운드 앰프 2.0 스테레오 스피커 Amplif

Smarter Shopping, Better Living! Aliexpress.com

ko.aliexpress.com

이것도 가격이 $11대의 저렴한 가격 일단 주문하고

 

음... 그러고 나니 진공관 Pre-Amp에 Class-D Power-Amp 라니 이 무슨 독특한 조합인가? ㅋㅋㅋ

이왕 이렇게 된거 제대로 된 혼종을 만들어 보기로 한다.

 

일단 머리에 떠오르는대로 막 
진공관 프리앰프 - TPA3116 파워앰프를 가운데 두고
출력 스피커로는 4인치 풀레인지 달고 아쉬우면 1인치 트위터 추가하고
입력으론 블루투스 오디오 리시버 모듈 알리에서 싼거 하나사고, 예전에 사놓고 안쓴 SBC인 Orange PI PC에 안드로이드 설치해서 MUX로 입력 받고, 안드로이드 깔았으니 터치스크린도 하나 달고
이왕이면 움직일 수 있게 파워뱅크도 전류소모량 체크해서 18650으로 구성해서 하나 달고

인클로저는 MDF로 하면 좋겠지만 이거 음질을 생각해서 만드는것도 아니고 목재 가공도 어렵고하니
역시 집에서 몇년째 묵히고 있는 폼보드로 적당히 포개서 만들어 보는걸로 하고

OK!

일단 파워쪽은 구성전까지 어댑터로 테스트 하기로 하고 필요한걸 더 주문하자.
- 4인치 풀레인지 : 삼미 CW-100B25 50W 4인치 풀레인지 \8,400 (+ 배송비 \3,000)
- 1인치 풀레인지 : 알리익스프레스 $1.73 (+ 배송비 $0.75)

https://ko.aliexpress.com/item/32821371907.html?gatewayAdapt=glo2kor&spm=a2g0o.9042311.0.0.27424c4d2JE3DH 

 

2148.0₩ 16% OFF|고품질 범용 고효율 미니 돔 트위터 라우드 스피커 2x500W 라우드 스피커 자동차용

Smarter Shopping, Better Living! Aliexpress.com

ko.aliexpress.com

 - 블루투스 리시버 보드 : 알리익스프레스 bluetooth 5.0 보드 $1.16 (+ 배송비 $0.76)

블루투스 오디오 수신기 보드, 블루투스 4.1 5.0 MP3 무손실 디코더 보드, 무선 스테레오 음악 모듈|Integrated Circuits| - AliExpress

 

1465.0₩ 3% OFF|블루투스 오디오 수신기 보드, 블루투스 4.1 5.0 MP3 무손실 디코더 보드, 무선 스테레

Smarter Shopping, Better Living! Aliexpress.com

ko.aliexpress.com

 - 7인치 Touch Screen : 7인치로 샀다. $42.88

IPS 7 인치 화면 AIDA64 LCD 디스플레이 미니 pc 터치 HDMI 모듈 1024x600 라즈베리 파이 3 Pi4 PC 모니터 moniteur 오렌지 파이|Display Screen| - AliExpress

 

47402.0₩ 28% OFF|IPS 7 인치 화면 AIDA64 LCD 디스플레이 미니 pc 터치 HDMI 모듈 1024x600 라즈베리 파이 3 Pi

Smarter Shopping, Better Living! Aliexpress.com

ko.aliexpress.com


자 이제 부품들이 다 오면 하나씩 하나씩 해자.

멋드러진 결과 따윈 나올리 없을테고 동작이나 잘 시켜보자 ㅋㅋㅋ

'Study 외 > DIY' 카테고리의 다른 글

[진공관 올인원 오디오 DIY] #2 - 동작 테스트  (0) 2022.04.06

지난 포스팅에서 무엇을 살것인가에서 ETF를, 그리고 ETF 종목의 조회를 어떻게 하는가 봤다

 

그리고 얼마에 살 것인가는 변동성 돌파 전략에서 K값의 결정에 따라 산다 정도로 설명했다.

 

일단 프로그램 전체를 가져와보자.

 

역시 기본적으로 책인 [파이썬 증권 데이터 분석] 에서 제공하는 github의 소스를 이용한다.

StockAnalysisInPython/ch08_03_EtfAlgoTrader.py at master · INVESTAR/StockAnalysisInPython · GitHub

 

GitHub - INVESTAR/StockAnalysisInPython

Contribute to INVESTAR/StockAnalysisInPython development by creating an account on GitHub.

github.com

다만 slack으로 메시지 보내는 방법은 수정되어야 해서 전에 slack 관련 포스팅과 같은 방식으로 수정하였다.

아래와 같이 post_message 함수 정의해서 사용했다.

def post_message(token, channel, text):
    response = requests.post("https://slack.com/api/chat.postMessage",
        headers={"Authorization": "Bearer "+token},
        data={"channel": channel,"text": text}
    )
    print(response)

내가 직접 짠 소스가 아니므로 여기에 모두 포스팅 하지는 못하겠고 이정도 수정은 필요하신 분이시라면 어렵지 않게 하실수 있을것이라 생각한다.

 

같은 과정으로 vscode 실행하고 새 파이썬 파일 만들어서 소스 복붙하고 위의 post_message 부분으로 수정하면 된다.

 

일단 나의 경우 AutoTrade.py라고 저장하였고. 이 AutoTrade를 실행하기전에 이전포스팅에서 설명했던 AutoConnect.py를 먼저 실행해서 CREON Plus와 연결을 한다. 그리고 이 AutoTrade.py를 실행하는 것이다.

 

우선 main 부분만 훑어 보자.

if __name__ == '__main__':
    try:
        symbol_list = ['A122630', 'A252670', 'A233740', 'A250780', 'A225130',
             'A280940', 'A261220', 'A217770', 'A295000', 'A176950'] #매수 대상 종목 리스트
        bought_list = []     # 매수 완료된 종목 리스트
        target_buy_count = 5 # 매수할 종목 수
        buy_percent = 0.19   #종목별 매수 비율 5 종목 * 19%씩 매수 = 95% 매수하고 5% 금액 남게 된다.
        printlog('check_creon_system() :', check_creon_system())  # 크레온 접속 점검
        stocks = get_stock_balance('ALL')      # 보유한 모든 종목 조회
        total_cash = int(get_current_cash())   # 100% 증거금 주문 가능 금액 조회
        buy_amount = total_cash * buy_percent  # 종목별 주문 금액 계산
        printlog('100% 증거금 주문 가능 금액 :', total_cash)
        printlog('종목별 주문 비율 :', buy_percent)
        printlog('종목별 주문 금액 :', buy_amount)
        printlog('시작 시간 :', datetime.now().strftime('%m/%d %H:%M:%S'))
        soldout = False

        while True:
            t_now = datetime.now() #현재시간
            t_9 = t_now.replace(hour=9, minute=0, second=0, microsecond=0)  # 9:00
            t_start = t_now.replace(hour=9, minute=5, second=0, microsecond=0) # 9:05 시작 시간
                                                                                      참고로 유동성 공급자 활동시간 9:05 ~ 15:20
            t_sell = t_now.replace(hour=15, minute=15, second=0, microsecond=0) # 15:15 매도 시간
            t_exit = t_now.replace(hour=15, minute=20, second=0,microsecond=0) # 15:20 종료 시간
            today = datetime.today().weekday() #금일 요일
            if today == 5 or today == 6:  # 토요일이나 일요일이면 자동 종료
                printlog('Today is', 'Saturday.' if today == 5 else 'Sunday.')
                sys.exit(0)
            if t_9 < t_now < t_start and soldout == False:
                                            #9:00~9:05 사이에 시작하기전 혹시나 남은 주식이 있으면 다 매도
                soldout = True
                sell_all()
            if t_start < t_now < t_sell :  # AM 09:05 ~ PM 03:15 : 매수
                for sym in symbol_list: # 매수대상 종목리스트에서
                    if len(bought_list) < target_buy_count: #매수 완료한 종목이 목표수보다 작으면
                        buy_etf(sym)    #매수
                        time.sleep(1)
                if t_now.minute == 30 and 0 <= t_now.second <= 5:   #30분마다 잔고 등의 정보를 알림
                    get_stock_balance('ALL')
                    time.sleep(5)
            if t_sell < t_now < t_exit:  # PM 03:15 ~ PM 03:20 : 일괄 매도
                if sell_all() == True:
                    dbgout('`sell_all() returned True -> self-destructed!`')
                    sys.exit(0)
            if t_exit < t_now:  # PM 03:20 ~ :프로그램 종료
                dbgout('`self-destructed!`')
                sys.exit(0)
            time.sleep(3)
    except Exception as ex:
        dbgout('`main -> exception! ' + str(ex) + '`')

일단 설명할 부분은 주석으로 달아놨고

여기서 매수할 종목 대상 리스트는 ETF든 KOSPI든 KOSDAQ이든 미리 알아서 집어넣어두면 된다.

그리고 얼마에 매수할것인지에 대한 결정은 buy_etf()함수에서 불러오는

아래의 get_target_price()에 함수에서 설정되는 K값 0.5로 결정된다.

def get_target_price(code):
    """매수 목표가를 반환한다."""
    try:
        time_now = datetime.now()
        str_today = time_now.strftime('%Y%m%d')
        ohlc = get_ohlc(code, 10)
        if str_today == str(ohlc.iloc[0].name):
            today_open = ohlc.iloc[0].open
            lastday = ohlc.iloc[1]
        else:
            lastday = ohlc.iloc[0]                                      
            today_open = lastday[3]
        lastday_high = lastday[1]
        lastday_low = lastday[2]
        target_price = today_open + (lastday_high - lastday_low) * 0.5
        return target_price
    except Exception as ex:
        dbgout("`get_target_price() -> exception! " + str(ex) + "`")
        return None

현재 K값을 0.5 상수로 두고 있는데 이를 변수로 두던 상수로 두던 값 역시 수정하면 된다.
다만 K값이 낮으면 매수가 쉽고 높으면 어렵다..... 당연하군 ^^;

실제로 이 프로그램으로 매수/매도를 해보질 않았다.
일단 함수단위 테스트를 먼저 해보자.

바로 위 get_target_price()에 KODEX 200(069500) 을 한번 테스트 해보자. 

일단 test2.py 라는 임의로 파이썬 파일을 만들고 AutoTrade.py에서 일부분만 테스트를 위해 좀 잘라서

다음과 같이 테스트프로그램을 작성해서 실행해본다.

import os, sys, ctypes
import win32com.client
import pandas as pd
from datetime import datetime
import requests
import time, calendar

# 크레온 플러스 공통 OBJECT
cpCodeMgr = win32com.client.Dispatch('CpUtil.CpStockCode')
cpStatus = win32com.client.Dispatch('CpUtil.CpCybos')
cpTradeUtil = win32com.client.Dispatch('CpTrade.CpTdUtil')
cpStock = win32com.client.Dispatch('DsCbo1.StockMst')
cpOhlc = win32com.client.Dispatch('CpSysDib.StockChart')
cpBalance = win32com.client.Dispatch('CpTrade.CpTd6033')
cpCash = win32com.client.Dispatch('CpTrade.CpTdNew5331A')
cpOrder = win32com.client.Dispatch('CpTrade.CpTd0311')  

def get_ohlc(code, qty):
    """인자로 받은 종목의 OHLC 가격 정보를 qty 개수만큼 반환한다."""
    cpOhlc.SetInputValue(0, code)           # 종목코드
    cpOhlc.SetInputValue(1, ord('2'))        # 1:기간, 2:개수
    cpOhlc.SetInputValue(4, qty)             # 요청개수
    cpOhlc.SetInputValue(5, [0, 2, 3, 4, 5]) # 0:날짜, 2~5:OHLC
    cpOhlc.SetInputValue(6, ord('D'))        # D:일단위
    cpOhlc.SetInputValue(9, ord('1'))        # 0:무수정주가, 1:수정주가
    cpOhlc.BlockRequest()
    count = cpOhlc.GetHeaderValue(3)   # 3:수신개수
    columns = ['open', 'high', 'low', 'close']
    index = []
    rows = []
    for i in range(count):
        index.append(cpOhlc.GetDataValue(0, i))
        rows.append([cpOhlc.GetDataValue(1, i), cpOhlc.GetDataValue(2, i),
            cpOhlc.GetDataValue(3, i), cpOhlc.GetDataValue(4, i)])
    df = pd.DataFrame(rows, columns=columns, index=index)
    return df

def get_target_price(code):
    """매수 목표가를 반환한다."""
    try:
        time_now = datetime.now()
        str_today = time_now.strftime('%Y%m%d')
        ohlc = get_ohlc(code, 10)
        print(ohlc)
        if str_today == str(ohlc.iloc[0].name):
            today_open = ohlc.iloc[0].open
            lastday = ohlc.iloc[1]
        else:
            lastday = ohlc.iloc[0]                                      
            today_open = lastday[3]
        lastday_high = lastday[1]
        lastday_low = lastday[2]
        target_price = today_open + (lastday_high - lastday_low) * 0.5
        return target_price
    except Exception as ex:
        print("`get_target_price() -> exception! " + str(ex) + "`")
        return None

target_price = get_target_price('A069500')
print("목표가 = " + str(target_price))

2022년 2월 24일 현재 실행결과 아래와 같이 나온다.

즉 KODEX200 의 열흘간 시작가, 최고가, 최저가, 종가 가 출력되고 이를 토대로

K값이 0.5일때 목표가는 \36642.5 원이라는 것이다.

그럼 이제 K값을 변화해서 살펴보자.

K = 0.3 일 때
K = 0.7 일 때

자 각각 K가 0.3, 0.7로 바꿔서 놓고 실행해보면 목표가가 0.3일 때 36561.5원, 0.7일 때 36723.5원 으로 바뀌는 것을 볼 수 있다.

K = 0.3 K = 0.5 K = 0.7
\36561.5 \36642.5 \36723.5

이 매수조건에 현재가가 5일 이동평균선과 10일 이동평균선 위에 있어야 한다는 조건이 추가되어 있는데

이 부분이 buy_etf() 함수에서 get_movingaverage() 함수를 불러 이동평균을 구하고 조건을 추가하는식이다.

...
        ma5_price = get_movingaverage(code, 5)   # 5일 이동평균가
        ma10_price = get_movingaverage(code, 10) # 10일 이동평균가
...
        if current_price > target_price and current_price > ma5_price and current_price > ma10_price:  
         


자 그렇다면 이제

1. 무엇을 살 것인가는 ETF 중에서 또는 관심가는 종목 중 골라서 종목코드를 매수대상 종목리스트 symbol_list에 넣어두면 되고

2. 얼마에 살 것인가는 위에 조건처럼 K값과 이동평균선 조건에 따라서 매수하고 장마감에 매도

이런 아주 기초적인 조건으로 매매는 시작할 수 있게 되겠다.

 

그러고보니 매수대상을 종목리스트에 넣어두는 것은 자동은 아니네 --a 

그리고 추가로 설명할 부분이 주문조건과 주문호가가 있는데 프로그램에서는 ETF를 기본으로 하고 있다보니

거래량이 다른 주식대비 많지 않아 비싼 가격을 지불하지 않도록 [최유리 FOK 매수 주문] 방법으로 매수하고

매도는 [최유리 IOC 매도] 방법으로 매도하도록 되어있다.


비록 아직은 매수대상 종목리스트는 수작업으로 하지만 프로그램의 실행은 윈도우가 알아서 실행하도록 해보자.

 

우선 PC가 켜지는 것은

 1) 켜두거나

 2) BIOS가 지원한다면 BIOS에서 해야하는데 각 회사마다 다르겠지만

   기본적으로 BIOS진입 - Advanced - ACPI Configuration - RTC Alarm Power On 에서 예약 부팅 을 해두면 된다.

 

그리고 PC가 켜지면 윈도우키 + S 를 누른뒤 "작업 스케줄러"로 검색/실행을 하면 아래와 같이 작업스케줄러가 실행이된다.

그리고 좌측 창의 [작업 스케줄러 라이브러리] 클릭하면 가운데 창이 아래 그림처럼 나오는데 그 창에서

우측 클릭 - 새 작업 만들기

그러면 나타나는 창에서

이름과 설명은 원하는 대로 작성하고 형광펜의 '가장 높은 수준의 권한으로 실행' 에 체크

그리고 트리거 탭으로 가서 '새로만들기' 누른뒤 나타나는 창에서 '매일' '오전 8:20' 그리고 아래에 '사용'에 체크

그럼 트리거가 하나 만들어진다.

그리고 동작탭으로 넘어가서 역시 '새로만들기'

설정의 프로그램/스크립트 에서는 찾아보기 버튼을 누른뒤 python.exe가 있는 폴더에 들어가서 선택해주고

인수추가에는 실행할 python 파일 이름 위 그림엔 AutoConnect.py 시작위치는 AutoConnect.py가 있는 폴더의 경로
그리고 확인을 누르면 된다.

 

그리고 같은 방법으로 8:30 정도에 AutoTrade.py도 등록해주면 윈도우즈의 작업스케줄러가 알아서 실행한다.

 


- 지금까지 대부분의 정보는 "파이썬 증권 데이터 분석" 이라는 책의 내용을 보고 정리한 내용이며 일부 현재 동작하지 않는 Slack의 requests 같은 부분은 내가 검색해서 수정하였음을 미리 밝힌다. 그래서 세세한 소스는 직접 책에서 제공하는 github로 링크하였다.

 

- 현재 나도 아직 이 방식으로 주식거래를 시작하지 않았다.  '주식투자자동화' 관련 포스팅은 여기서 끝나는게 아니고

일단 서둘러 해보고 싶은 분들을 위해 1부? 여튼 일단 시작할 수 있는 정도까지 서둘러 포스팅한다.

나는 여기서 종목을 골라서 리스트에 넣는 부분과 K값을 조금씩 조절하고 그에 따른 결과를 자동으로 기록하는 부분까지는 조금 더 프로그램하고 작은 금액이라도 실제 투자해볼 생각이다.

그 부분은 차근차근 여기다 포스팅하고 수익이 나던 손해가 나던 일정 기간 후 역시 결과도 포스팅 해 볼 예정이다.

 

일단은 여기까지!!

이전 포스팅을 보면 늘 실행하기전에 CREON Plus를 실행해야 한다는 말을 쓰곤 했는데

내가 항상 깜빡하고 CREON Plus도 실행하지 않고 실행해서 Error가 발생하곤 했기 때문이다.

추가로 CREON Plus 실행하고 비번 치고, 비번 또 치고 이러는것도 귀찮기도 하고 ㅎ

여튼 그래서 우선 할것은 CREON Plus 자동 실행 프로그램이다.

이 소스는 구매한 책인 [파이썬 증권 데이터 분석] 이 유용하게도 github에 소스도 제공해주는데 여기에 자동 실행 예제가 있다.

 

아래의 링크에 들어가보자.

StockAnalysisInPython/08_Volatility_Breakout at master · INVESTAR/StockAnalysisInPython · GitHub

 

GitHub - INVESTAR/StockAnalysisInPython

Contribute to INVESTAR/StockAnalysisInPython development by creating an account on GitHub.

github.com

위 링크의 8장 말고도 다른 장도 다양한 소스가 있으니 공부에 참고하면 좋을듯하다.

물론 책을 사서 보면서 해야겠지만 ㅎ 나도 책은 아직 보는 중

여기에 보면 ch08_01_AutoConnect.py 이라는 파이썬 파일이 있다.

-------------------------------------------------------------------------------------------------------
from pywinauto import application
import time
import os

os.system('taskkill /IM coStarter* /F /T')
os.system('taskkill /IM CpStart* /F /T')
os.system('taskkill /IM DibServer* /F /T')
os.system('wmic process where "name like \'%coStarter%\'" call terminate')
os.system('wmic process where "name like \'%CpStart%\'" call terminate')
os.system('wmic process where "name like \'%DibServer%\'" call terminate')
time.sleep(5)        

app = application.Application()
app.start('C:\CREON\STARTER\coStarter.exe /prj:cp /id:userid /pwd:pa$$word /pwdcert:certPa$$word /autostart')
time.sleep(60)

-------------------------------------------------------------------------------------------------------

14번째줄 (끝에서 두번째줄) userid 에 ID 넣고, pwd에 password 넣고 pwdcert에 인증서암호 넣고

그리고 Autoconnect.py 로 저장하고 실행하면 끝

소스의 설명은 딱히 할게 없다. 

11번째 줄까지는 혹시 CREON Plus가 실행하고 있으면 끝내고

5초 대기

CREON Plus 를 실행하고 60초 대기 

그리고 이 소스에서 
-------------------------------------------------------------------------------------------------------
from pywinauto import application
import time
import os

os.system('taskkill /IM coStarter* /F /T')
os.system('taskkill /IM CpStart* /F /T')
os.system('taskkill /IM DibServer* /F /T')
os.system('wmic process where "name like \'%coStarter%\'" call terminate')
os.system('wmic process where "name like \'%CpStart%\'" call terminate')
os.system('wmic process where "name like \'%DibServer%\'" call terminate')
time.sleep(5)    

-------------------------------------------------------------------------------------------------------

이 부분만 Disconnect.py로 저장하고 끝낼때 종종 쓰곤 한다. ㅋ

 

자 그럼 이제 주식투자 자동화 프로그램을 해보도록 하자.

 

책에서 설명하는 주식 자동프로그램의 기본전략은 변동성 돌파전략이다. 

그럼 변동성 돌파전략이란 무엇인가?

 

변동성 돌파전략(volatility breakout strategy)이란 선물 트레이더의 대가라고 하는 래리 윌리엄스라는 사람이 개발한 투자전략으로 가격이 전일 가격범위의 K% 이상이 될 때 매수하고 장마감시 매도해서 수익을 실현하는 전략이라고 

책에 설명되어 있다.

 

여기서 중요한건 그럼 무엇을 (어느종목을) 과 언제 (K% 이상이 될 때) 의 결정이 가장 중요하지 싶다.

이건 책을 다 봐야 알것 같은데 책을 아직 다 보지 않았... (다 보면 나오긴 할까?)

여튼 나같은 초보에게 가장 쉽게 이해되는 그림을 첨부해보고자 구글링 해봤지만

그래도 책에 나온 그림이 가장 쉽게 이해되는 그림이었다.

변동성 돌파 전략 (책 파이썬 증권 데이터 분석 371페이지 그림)

그렇다면 수많은 종목 중에서 저렇게 스윙하는 종목들을 매수하게 된다고 가정하고

내 자금을 그 종목 1개만 몰빵해서 사기는 위험하고 그런 종목들 중 몇종목을 살것인지도 결정하기도 해야하겠다.

그리고 하루에 한번은 매수/매도도 해야겠고

그럼 그 수수료도 만만치 않을것이다. 

그래서 수수료를 생각해보면 이전에 대신증권은 0.015% 또는 월정액 15000원 + 0.0088% 라고 했는데....

"세금" 이 있다!!

 

CREON 트레이딩 - 제휴은행 계좌개설 - 크레온 (creontrade.com)

 

크레온

대신증권 온라인 주식 거래 서비스. 비대면계좌개설, 수수료 혜택, 주식시세, 종목추천, 투자정보 제공

www.creontrade.com

 

위 링크를 보면 수수료가 나와있는데 "매매관련세금" 탭이 있는 것을 볼 수 있다. 여기를 보면

KOSPI는 거래세 0.08% + 농특세 0.15% = 0.23%

KOSDAQ은 거래세 0.23%

ETF는 0%


정리하면

  매수 매도 합계
KOSPI 0.015% 0.015% + 0.23% 0.26%
KOSDAQ 0.015% 0.015% + 0.23% 0.26%
ETF 0.015% 0.015% 0.03%

하루에 한번꼴로 매수/매도를 하는데 KOSPI 또는 KOSDAQ과 ETF는 약 10배 가량 차이가 난다!
즉 거래를 자주하는데는 ETF가 유리하다!!

물론 KOSPI나 KOSDAQ이 훨씬 수수료 이상의 수익을 내준다면 상관이 없겠다 ㅎ

일단은 ETF 위주로 진행해보는 걸로 계속 진행해보자

 

그 ETF 중에도 당연히 시가총액이 크고 거래량이 많은 종목 중에서 선택을 하는것이 좋겠다.
그래서 ETF 종목 정보를 구해보도록 하자.

 

1. pip install beautifulsoap4 설치

2. pip install pandas 설치

3. pip install selenium으로 selenium 설치

4. Chrome 브라우저 실행하고 주소창에 chrome://version 입력해서 버전 확인  (나의 경우 98.0.4758.102)

5. https://chromedriver.chromium.org/downloads

 에서 버전에 맞는 chromedriver를 다운받고 압축을 푼다음에 chromedriver.exe 파일을 c:\myPackage 폴더 만든후 이 폴더로 복사

6. c:\myPackage의 chromedriver.exe를 관리자권한으로 실행하도록 설정

7. 아래의 파이썬 증권데이터 분석 책에서 제공하는 github 에서 소스

 StockAnalysisInPython/ch08_02_DynamicPageScraping_NaverETF.py at master · INVESTAR/StockAnalysisInPython · GitHub

 

GitHub - INVESTAR/StockAnalysisInPython

Contribute to INVESTAR/StockAnalysisInPython development by creating an account on GitHub.

github.com

 

8. vscode 실행시켜서 새파일(파이썬파일) 만들기 후 복붙  (나의경우 ScrapingETF.py)

9. 저장 후 터미널에서 python ScrapingETF.py를 실행하였더니!

아.. 이건 또 무슨 에러냐... 구글 검색해본 결과 lxml 이 없는게 이유

그럼 터미널에서 pip install lxml 하면 설치하는게 보인다.

 

10. 그리고 다시 실행하면

위와같이 naver에서 518개의 ETF종목의 정보를 가져온것을 확인할수 있다. 순서는 시가총액 순이다.
pandas로 읽은 이정보를 잘 추려서 이 중에서 어떤 종목을 선택할 것인지 이것도 매우 중요한 요소일것이다.

 

오늘은 일단 여기까지!

 

이 주식자동화를 프로그램을 돌려놓고 수익이 알아서 막 나면 얼마나 좋을까?

하지만 수익은 커녕 손실만 계속 발생한다면 그것도 큰 문제다.

수익이 나던 손실이 나던 적어도 이 프로그램이 현재 뭘하고 있는지 내가 어디에 있던 나에게 알려는 줘야 한다. 

무슨 종목을 얼마에 체결하는지 같은 정보 등등

여튼 최악의 상황에서 원격데스크탑으로든 무슨 수를 써서든 주식용 컴퓨터에 접속을 해서 프로그램을 멈추든 하지 않겠는가.

 

 

이런 정보를 가장 많이들 사용하는 카카오톡으로 그때 그때 보내주면 좋겠는데 뭐 그건 아직 모르겠다.

카카오톡도 api가 있는걸로 아는데 그건 나중에 공부해보는걸로 하고

일단 이것 역시 시키는대로 ^^;;

 

Slack은 업무용 메신저로 엄청 많이 사용되는 것으로 알고 있다. 미국회사던가 여튼 이번에 코로나 사태에 '줌'과 함께 꽤나 좋은 실적을 낸 회사로 알고 있다.

잡설은 그만하고 슬랙에 접속해서 가입을 한다.

GOOLGE로 가입을 해도 되고, 로그인 버튼을 누르고 우측 상단 계정생성을 눌러 계정을 만들면 된다.

 

https://slack.com/

 

Slack은 미래의 업무가 이루어지는 곳입니다

Slack은 여러분의 팀과 소통할 새로운 방법입니다. 이메일보다 빠르고, 더 조직적이며, 훨씬 안전합니다.

slack.com

 

이메일을 입력하면 6자리 인증코드를 확인하는 과정이 나오고

입력했던 본인의 이메일 slack에서 보낸 6자리 인증코드를 입력해서 다음으로 넘어가면  workspace 생성 화면이 나온다.

여기서 workspace 이름을 적당히 지어둔다. 위에선 jslee-stock이라고 지어줬다. 다음을 눌러 다음단계로 넘어가면

채널이름을 설정하는데 위에선 stock이라고 지어줬다. 그리고 다음

여럿이서 같이하는 작업이 아니고 혼자 쓸것이므로 팀원추가가 필요없다 형광펜으로 칠한 이단계 건너뛰기를 하면 기본설정이 끝이난다.

PC에서는 위와같은 초기화면이 뜨고

핸드폰 IOS, Android 모두 Slack 앱이 있는데 다운로드하여 접속하면 아래와 같은 화면이 뜬다.

위의 가입-설정의 워크스페이스와 이름이 jslee-stock과 jslee 로 다른데 가입-설정 과정을 사진으로 남기려고

새로 가입하여 만든 워크스페이스인 jslee-stock과 기존에 쓰던 워크스페이스인 jslee와 이름이 다르게 되었다.

 

다음은 이렇게 만든 slack 워크스페이스에 알람을 보내준 슬랙알람봇을 만들어준기 위해 아래의 링크에 접속한다.

api.slack.com

 

Create an App을 눌러 app을 만든다.

App Name 을 적당히 적고 (위의 예에선 jslee-stock-bot)

App Name 아래의 workspace에서 본인의 워크스페이스를 선택한다.(jslee-stock)

 

그러면 위와같이 App이 만들어지고 기본 정보들이 표시된다.

이제 이 알리봇에 권한을 줘야하는데 

왼쪽 메뉴에서 형광펜으로 칠한  OAuth & Permissions 을 클릭 하고 우측 메인화면을 스크롤 다운하면

Scope / Bot Token Scopes 가 나오는데 여기서 Add an OAuth Scope를 누르면 다음과 같이 여러 권한이 나온다.

이 여러권한 중 우리는 알림봇이 우리의 채팅창에 메시지를 보내는 것이므로

형광펜으로 칠한 chat:write 권한을 선택한다.

그리고 스크롤 업해서 위로 올라가다 보면 위 그림처럼 OAuth Tokens for Your Workspace의 Install to Workspace가 나오는다. 클릭해주자.

그러면 위 그림과 같이 허용할꺼냐고 묻는데 허용!

자 여기서 중요한게 뭐냐면 앞으로 우리가 작성하는 파이썬 프로그램은 이 알림봇에게 메시지를 보낼때

이 알림봇을 구분하는 구분자 같은게 있는데 그게 아래 그림의 Bot User OAuth Token 이다.

이 부분이 나중에 소스에 사용됨을 기억하자.

즉 파이썬을 작성한 코드에서 메시지는 이 Token을 가진 알림봇에 메시지를 전달하고

이 알림봇은 내 채팅창에 메시지를 전달하는 것이다.

 

이를 위해 한가지 더 작업해둘 사항이 있다.

다시 slack 채팅창으로 가서

형광펜 부분을 누른다. 그러면 아래와 같은 창이 뜨는데

통합 탭에서 앱/앱추가 를 눌러 만들어둔 앱을 추가해준다.

 

그러면 아래와 같이 jslee-stock-bot님과 함께 참여했다고 뜬다.

 

자 그럼 이제 이 slack 채팅으로 메시지를 보내보도록 하자.

지난번에 작업했던 대로 vs code 를 실행하여 임의로 파이썬 파일을 만들고 테스트를 해보도록 하자.

일단 msgtest.py 로 작업한다.

 

그 전에 해야할게 있는데 slack으로 메시지를 보내기 위해 파이썬은 requests 라는 것을 사용한다.

그래서 request를 깔아야하는데 역시 pip install requests 로 설치하도록 한다.

역시 이미 설치되어 있어서 위와 같은 메시지가 나온다만 설치되어 있지 않을 경우 설치되는 과정이 표시될 것이다.

 

설치가 되었다면 아래의 소스와 같이 타이핑 해보자

 

import requests
import win32com.client

def post_message(token, channel, text):
    response = requests.post("https://slack.com/api/chat.postMessage",
        headers={"Authorization": "Bearer "+token},
        data={"channel": channel,"text": text}
    )
    print(response)
 
myToken = "여기는 본인이 사용하는 고유의 Bot User OAuth Token 값을 넣어야 함!!"

# 연결 여부 체크
objCpCybos = win32com.client.Dispatch("CpUtil.CpCybos")
bConnect = objCpCybos.IsConnect
if (bConnect == 0):
    print("PLUS가 정상적으로 연결되지 않음. ")
    exit()
 
# 현재가 객체 구하기
objStockMst = win32com.client.Dispatch("DsCbo1.StockMst")
objStockMst.SetInputValue(0, 'A005930')   #종목 코드 - 삼성전자
objStockMst.BlockRequest()
 
# 현재가 통신 및 통신 에러 처리
rqStatus = objStockMst.GetDibStatus()
rqRet = objStockMst.GetDibMsg1()
print("통신상태", rqStatus, rqRet)
if rqStatus != 0:
    exit()
 
# 현재가 정보 조회

offer = objStockMst.GetHeaderValue(16)  #매도호가
post_message(myToken,"#stock","삼성전자 현재가:" + str(offer))

(위 소스는 CREON Plus 자료실의 주식현재가 조회 소스에 Slack 메시지 전송을 덧붙인 예제임)

 

위 코드를 작성할때  11행의 반드시 myToken 값은 위의 api.slack.com 에서 표시되는 본인의 Bot User OAuth Token 값을 넣어줘야만 한다.

 

그리고 이 소스를 실행하기전에 CREON Plus 를 반드시 실행하고 위 소스를 실행한다.

실행은 터미널에서 python msgtest.py

그러면 터미널의 결과에서도 아래와 같이 조회가 완료되었고 Response [200] -이게 잘 되었다는 것- 으로 표시되고

다음과 같이 브라우저의 slack 채팅창에서도 메시지가 표시되고

핸드폰에 (slack에 미리 로그인한) 알림이 뜨는 것을 확인할 수 있다.

앞으로 이 파이썬의 requests를 이용해서 여러 정보를 slack의 메시지로 보내고 내가 어디에 있던 핸드폰 또는 브라우저 등으로 확인 할 수 있겠다.

 

오늘은 여기까지!

사실 파이썬이야 command prompt 에서도 할수 있겠지만 불편하고

많이 쓰이는 파이참을 써도 되겠다만
책과 조코딩 유튜브에서 시키는대로 할란다.. ㅋ 이 부분은 정말 다르게 한다고 별 문제가 발생할것 같지는 않다.

여튼 아래의 링크에서 VS Code를 다운받아 설치한다.

Download Visual Studio Code - Mac, Linux, Windows

 

여기서 보면 user installer가 있고 system installer 가 있는데 두개의 차이점은

user 는 현재 설치하고 있는 계정만 사용가능

system은 모든 사용자 사용가능
개인 pc에다 설치하니까 system으로 설치하는게 속편할듯!

VS Code는 그냥 다운받고 설치
그리고
Creon의 파이썬 예제 테스트 먼저 한번 해보기위한 사전작업

본인이 원하는 폴더를 하나 만든다. (나는 유튜브에 나오는대로 c:\stockauto\ 그대로 만듬)

앞으로 이 폴더에 파이썬 소스들을 하나씩 만들 예정이다.

 

VS Code 실행한다.

메뉴바에서 파일/폴더열기 에서 위에서 만든 폴더를 선택한다.

 

위 사진은 임의로 temp 라는 폴더를 만들었을 뿐...

그리고 이 과정에서였는지 언제였는지 vs code에서 파이썬 확장 설치를 묻는데

설치 안해도 된다. 설치 하면서부터 뭔가 복잡하게 꼬인다.. 이건 내가 vs code를 잘 몰라서 그럴수 있음

 

그리고 파이썬을 실행하는 터미널을 표시하려면 역시 메뉴바에서 보기/터미널 을 누르면 터미널을 볼수 있다.

위 그림의 우측 상단을 보면 powershell로 실행된것을 볼 수 있는데 유튜브에서는 cmd로 하도록 한다.

그런데 해보면 powershell도 별 상관없었다 

어쨌든 cmd로 하려면 저 powershell이라고 쓰인 옆에 + 버튼을 누르면 Command Prompt를 볼수 있는데 이를 추가하면 cmd도 사용할수 있다.

이제 CREON Plus API를 실행할수 있는 파이썬 라이브러리를 설치해야하는데

명령 프롬프트에 다음과 같은 명령어를 실행한다.

pip install pywinauto

나는 이미 설치되어 있어서 위와 같이 뜨는데 여튼 별문제 없으면 설치하는 표시등이 나타난다.

그런데 보통은 여기서 그냥 넘어가지 않는다.

위 그림처럼 Fatal Error 가 발생하는데...

 python -m pip install pywinauto 

이렇게 실행하면 된다고 하는데 이에 앞서

기본적으로 vscode도 관리자 권한으로 실행되도록 되어야 함을 잊지 말자.

(파이썬 실행파일 관리자권한 실행하도록 했던것과 동일)

파이썬, vscode 모두 관리자권한 실행이면 문제없이 설치되는것이 정상이다.

 

pywinauto까지 정상적으로 설치되었다면 기본 예제를 실행해보자.

vscode의 좌측 탐색기? 에서 아래 그림의 표시부를 눌러 새파일을 추가하고 이름을 test.py 로 만든다.

물론 이름은 맘대로 만들고 확장자는 파이썬의 확장자인 .py로 해야한다.

그리고 크레온 플러스 API 사이트에서 예제를 복사해서 테스트 해보도록 한다.

아래의 링크에 들어가서 CREON Plus(API) / 자료실 

크레온플러스자료실 - 크레온 (creontrade.com)

그리고 언어에서 파이썬을 클릭, Page 3을 클릭하면 처음에 종목정보 구하는 예제가 나온다.

소스 복사해서 test.py에 붙여넣기

그리고 파일을 저장하고

터미널에서 python test.py 를 타이핑하여 실행해보도록 한다.

자 그럼 위와같이 잘 실행되는것을 볼 수 있다. 

 

혹시 이런 실수를 할지도 몰라 적어두자면 실행이 정상적으로 안된다면

이건 당연히 CREON Plus를 접속을 안했기 때문이다. 이 모든것은 CREON Plus를 접속을 해야 CREON Plus API 서비스를 사용할 수 있다. 접속여부는 아래그림처름 작업표시줄 아이콘으로 확인해보면 된다.

 

우선 당연히 주식거래이니 만큼 증권계좌가 필요하다
다행히 그동안 사용하던 계좌가 대신증권이었... 다고 해도 원래 내 거래계좌를 가지고 할순 없고 ㅋ
여튼 대신증권에서 제공하는 API가 가장 사용성이 좋은가보다.

책에서 아래와 같이 비교하고 있다 (현재 어떤지 내가 정확히 비교한게 아니므로 다를수 있음에 주의)

  키움증권 Open API+ 대신증권 CREON 플러스 API 이베스트증권 xingAPI
제공방식 OCX COM COM, DLL
파이썬지원 보통 좋음 보통
API 사용성 보통 좋음 좋음
API거래수수료 0.015%(HTS수준) 0.015%(HTS수준) 또는
월정액 15000원 + 0.0088%
0.015%(HTS수준)

여튼 원래 사용하던 대신증권에 계좌를 하나 추가하였다.

 

그리고 아래 페이지에 크레온 HTS 프로그램을 다운로드 한다.
다운로드 센터 - 크레온 (creontrade.com)

 

크레온

대신증권 온라인 주식 거래 서비스. 비대면계좌개설, 수수료 혜택, 주식시세, 종목추천, 투자정보 제공

www.creontrade.com

다운로드 후 설치 

그리고 바탕화면에 있는 CREON 아이콘을 실행하면 아래와 같은그림이 뜨는데 위쪽에 형광펜으로 칠해놓은것 같이 creon plus 탭 이것으로 앞으로 모든것을 동작 시킬 것이다. (별도로 CREON PLUS 아이콘도 생기는데 그걸로 해도 된다)

 

그리고 작업표시줄 CREON PLUS 아이콘에서 마우스 우측버튼을 누르면 "주문 오브젝트 사용동의" 이걸 눌러서 API 사용을 할수 있게 해줘야 한다.

 

그리고 "주문내역 확인 설정" 을 누르면 아래의 그림과 같은 창이 뜨는데 형광펜으로 칠한것과 같이 체크박스를 "해제" 해주어야 자동으로 주문할때 확인을 안해도 알아서 할수 있게 될 것이다.


일단 이걸로 계좌 관련된건 설치가 되었고.... 그러고 보니 먼저 나와야 할건 파이썬 설치였는데 ...
뭐 나중에 설치한다고 어찌 되는건 아니니 ㅋ

책과 유튜브에서는 파이썬 3.8 버전의 설치를 권장한다. 최신의 버전을 설치해서 실험해보고자 하였지만 괜히 시스템 꼬일까 싶어 그냥 시키는대로 따라하기로.. ㅎ

내가 설치한건 파이썬 3.8.6 32비트 버전 (32비트 버전으로 하란다)

아래 링크에서 바로 다운 받을수 있고
https://www.python.org/ftp/python/3.8.6/python-3.8.6.exe

아니면 Python Releases for Windows | Python.org 여기 가서 3.8.6 x86 다운받으면 된다.

 

설치과정에서 반드시 "Add Python 3.8 to PATH" 를 체크해주고 

"Customize Install" - 모두 체크



또 모두체크

 

그리고 설치 경로에서 본인이 원하는 설치경로 지정 (난 C:\python38-32 폴더 만들어서 설치)

하고 설치한다.



설치 후 시스템 - 고급 시스템 설정 - 환경변수 - 시스템변수 - path 에 위의 설치경로의 path 지정해준다.

아래 그림과 같이

 

확인 - 확인 - 확인

 

그리고 python 설치한 경로로 가서 관리자 권한으로 실행할수 있도록 하여야 한다.

 

python.exe 와 pythonw.exe 파일에 마우스 우측버튼 - 호환성 - 관리자 권한으로 실행 클릭 으로 항상 관리자 권한으로 실행할 수 있도록 한다.

 



일단 오늘은 여기까지

 

그러고보니 주식투자 - 투자라고 하니 뭔가 거창해보인다만 적은 금액임 - 를 한지

어느새 5년차에 접어든것 같다.

초기에는 이래저래 시행착오도 많았고 나름 공부도 많이 해보고 나름 나만의 기준을 만들어
그동안 연평균 약 10% 이상의 꾸준한 수익을 내고 있다는 것은 매우 만족스럽다.

내가 직접 투자를 하는 원칙은
나만의 우량종목에 많이 분산투자하고 겁나 오래 기다린다. 라는 매우 단순한 방법이다.
보통 2,3년씩 투자하는 방식이긴 하다.

뭐 그래서인지 프로그램이 자동매매하게 하는것에 더 관심을 가지게 되었는지도 모르겠다. 

나의 투자방식과 반대이니 ㅎ

여튼 이제부터 블로그에 작성할 모든것은 다음의 책 "파이썬 증권 데이터 분석"
과 유튜브 "조코딩" 다음의 링크를 기본으로 한다.

https://youtu.be/Y01D2J_7894
https://youtu.be/xqlG-aEEa3Q
https://youtu.be/D2nZnmECTo8

https://youtu.be/5bTxyBeOVkA?list=PLU9-uwewPMe0fB60VIMuKFV7gPDXmyOzp 

 

책 당연히 내돈내산! 아직 읽진 않음 ㅋ

 

자 이제 정보는 대충 알아뒀고

 

실행할 PC는 내가 출근하기 전부터 켜지기 시작해서 최소 3시에서 퇴근전까지는 켜져있어야 하니 저전력 PC가 필요하다.
이거 하는데 고성능 사양의 PC가 필요할까 싶어서 전에 가지고 있던

J1900 CPU에 RAM 4G의 타오나스 에 셋팅해보았다.

동작은 하는데 너무 느리다 ㅠㅜ
그래서 집에서 나름 저전력 홈시어터 용으로 사용하는 J5040 CPU에 RAM 8G에 셋팅해 보았는데 나름 만족스럽게 돌아갔다.

 

왼쪽 J1900 RAM4G 타오나스 (PASSMARK 1131, TDP 10W) , 오른쪽 J5040 RAM 8G 타오나스 케이스 (PASSMARK 3578, TDP 10W)

 

뉴에그에서 직구한 J5040보드는 케이스를 타오나스케이스를 사용하기에 두 PC의 생긴건 똑같다 ㅋㅋㅋ
여튼 J5040 PC를 사용하기로 결정하고 J1900 PC는 뭐에 쓸지는 다시 생각해보자 ㅎ


그리고 기본적인 알고리즘의 원칙은

1. 단순하게 작성한다.

2. 매수/매도는 최소화

 

1번의 단순하게 작성한다는게 코딩을 단순하게 쓴다는 의미보다는 매도/매수의 원칙을 최대한 단순하게 세운다 라는 것임 괜히 이것이 복잡해진다고 크게 달라질것 같진 않다.

다만 이 기준값 두어가지를 결정하는 것과 종목의 선정을 딥러닝이던 머신러닝이던 배워가며 진행해보려고 한다.

그럼 다음 포스팅은 셋팅!

내가 오토바이를 타게 된 계기는 무엇이었을까?

 

고등학교 시절에도 술,담배는 물론 커피나 탄산음료 그리고 박카스 조차도 좋지 않은건 입에도 대지 않고

 

유일한 일탈행위라면 도서관에 안가고 걸으며 이 생각,  저 생각에 잠기는 것이 다였던 참 말잘듣는 학생이었는데 ㅋㅋㅋ

 

더 기억이 가물가물 해지기전에 왜 오토바이를 타게 되었는지부터 기록해두려고 한다.

 

 

92년 재수생활을 마치고 93년 대학에 입학하고 부터 아르바이트를 했는데 93년도에 아르바이트를 하던 곳 형이

 

일 마치고 청량리에 술한잔 하러 가자고 했었다.

 

그때 그 형의 오토바이 뒷자리에 태우고 갔는데 출발하기전에 무서웠던게 달리기 시작하니 시원한 바람과 함께 정말 기분이 좋았던 기억이 

 

아직도 생생하다.

 

아마 그때 내가 가지고 있던 오토바이에 대한 선입견? 편견? 이 많이 깨졌던것 같다.

 

 

 

94년 국립극장에 위치한 지화자 라는 한정식집에서 아르바이트를 하고 있던 때

 

그곳은 바쁜 점심시간이 지나면 3시부터 5시까지 쉬는 시간 + 준비 시간을 가지는데 그 때면 어슬렁 어슬렁 밖으로 나와 담배를 피곤 했다.

 

어느날 국립극장 앞을 도로를 지나던 할리를 타는 백발 긴머리의 할아버지를 보게되는데

 

늘상 노래를 흥얼거리며 타고 앞으로 지나가신다.

 

자주 들으니 뭐 손녀를 데리러 간다 어쩐다 이런 내용의 자작곡? 이다 ㅋ

 

여튼 그 할아버지가 참 멋지게 보였다. 저렇게 나이 들고 싶었다.

 

 

 

일단 오토바이를 탈 줄 알아야겠다라는 생각에 두달간 50만원의 알바비를 모았다. 

 

그리고는 50만원을 두 손에 꼭 쥐고

 

국립극장 바로 아래쪽에 택시타고 기본요금이면 갈 수 있는 퇴계로 오토바이 상가로 내려가서

 

제일 처음에 눈에 띈 가게에 들어갔다.

 

오토바이 관련해서 아는게 하나도 없던 나는 그저 그곳 사장에게 

 

나에겐 50만원이 있는데 그에 맞는 상태좋은 오토바이를 한대 달라고 얘기한게 다였다 

 

원하던 기종이고 뭐고 없이 ㅋㅋ

 

아마 그 가격대에 맞는 오토바이 두어대를 보여주었고 나는 그 중에 가장 맘에 들었던 오토바이를 사기로 한다

 

흐릿한 기억에 VF와 TN을 보여주었던것 같고 VF는 도로 많이 굴러다녀서 싫었고 소위 쌍라이트!! TN이 그렇게 멋져보였었드랬다 ㅋㅋ

 

 

 

(애석하게 내가 남겨둔 사진은 없고 사진은 http://m.blog.naver.com/firstceo80/140157105197 서 퍼왔습니다)

 

내가 샀던 놈은 사진의 빨간색이 아닌 파란색!

 

지금 생각하면 나도 꽤나 객기? 같은게 있었던것인지

 

상태도 모르고 그냥 사기로 하고

 

또 센터사장에게 돈을 지불하고 부탁을 해야했다 ㅋ

 

나 오토바이 면허도 없고 탈줄도 모른다고 저 위 국립극장까지 나 뒤에 태우고 배달 좀 해달라고 돌아올때 택시비는 드리겠다고 ㅋㅋㅋ

 

그 사장도 아마 어이없었을것 같다.

 

그래도 직원한명 시켜서 나 뒤에 태우고 국립극장까지 가라고 해주고 고마웠다.

 

그 직원은 생각지도 않은 배송을 하고 또 생각지도 않은 일을 하고서야 나와 헤어질 수 있었다. ㅋㅋㅋ

 

내가 국립극장 주차장에 도착한 직원에게 택시비를 주기전에 나 전혀 모르니 기본적인 조작법만 알려달라고 했기 때문이다.

 

그 직원분의 어이없어하는 표정 ㅋ

 

그래도 친절하게 왼손 레버가 클러치고, 오른손 레버가 앞브레이크, 왼발은 기어, 오른발은 뒷브레이크, 방향 지시등은 이렇게 켜고

 

기어는 클러치 잡고 1-N-2-3-4... 5단이 있었던가? 여튼 그것도 설명해주었다.

 

그리고 잘타라는 한마디와 함께 택시타고 가시고

 

난 그때부터 면허를 딸 때까지 3개월간 국립극장 주차장에서 연습을 했드랬다.

 

 

서점가서 오토바이 타는 법 관련 책을 사고

 

출발하는 법, 기어 바꾸는 법, 사이드 미러 보는 법 등등 매 과정을 일주일 정도씩 착실히 연습했다.

사실 마음은 2종소형면허를 따고 싶었지만 원서접수하고 늦잠자기, 실제로 가도 어려워서 떨어지기등으로 결국 실패

일단 가지고 있는 TN125를 타야하니 원동기면허 접수하였는데 원동기면허는 한방에 합격했드랬다.

 

도봉면허시험장.

여튼 그렇게 시작했었다.

 

 

 

 

 

'끄적:Scrawl > 탈것:Vehicle' 카테고리의 다른 글

기린 - Premium Edition DVD -  (0) 2012.11.05
Mercedes Benz 조으네~  (0) 2012.10.31
SLK230K 시승기?!  (7) 2012.09.03
'기린' 영화화 소식!!!  (4) 2011.07.16
랠리카에 일반인 탑승 ㅋㅋㅋ  (7) 2011.04.11

사실 내가 밖에 나가서 뭐 영상 보고 그럴일은 별로 없긴하다만 그 별로 없을 때를 대비해서 AirVideo를 설치를 시도


기본적으로 Airvideo는 리눅스용 서버 프로그램을 제공하지 않는다.


그래서 다음 링크를 참조해서 설치 (http://titanwing.tistory.com/entry/Airvideo-server-%EC%84%A4%EC%B9%98)


1. ffmpeg 설치


 1) 설치를 위해 필요한 프로그램 우선 설치

sudo apt-get install build-essential yasm libmp3lame-dev libfaad-dev libx264-dev git-core pkg-config



 2) 설치를 위한 폴더 생성 및 이동 그리고  설치프로그램과 ffmpeg 다운

sudo mkdir /opt/airvideoserver/

cd /opt/airvideoserver

sudo wget http://inmethod.com/airvideo/download/linux/alpha6/AirVideoServerLinux.jar

sudo wget http://inmethod.com/airvideo/download/ffmpeg-for-2.4.5-beta7.tar.bz2

( 정확한 이유는 모르겠으나 현재는 참고사이트의 링크로는 안됨, 그리고 ffmpeg-for-2.4.5-beta7 버전으로 해야함, 참고사이트의 beta6로는 컴파일 에러 )


 3) 압축해제 및 컴파일

sudo tar jxvf ffmpeg-for-2.4.5-beta7.tar.bz2

cd ffmpeg

sudo ./configure --enable-pthreads --disable-shared --enable-static --enable-gpl --enable-libx264 --enable-libmp3lame

sudo make

sudo make install 


2. mpeg4ip-server 설치


libvpx0 

sudo wget http://free.nchc.org.tw/ubuntu//pool/main/libv/libvpx/libvpx0_0.9.6-1_amd64.deb


libmpeg4ip 

sudo wget http://free.nchc.org.tw/ubuntu//pool/multiverse/m/mpeg4ip/libmpeg4ip-0_1.6dfsg-0.2ubuntu8_amd64.deb


libavutil51

sudo wget http://free.nchc.org.tw/ubuntu//pool/main/liba/libav/libavutil51_0.8.10-0ubuntu0.13.10.1_amd64.deb


libmp4v2 

sudo wget http://free.nchc.org.tw/ubuntu//pool/multiverse/m/mpeg4ip/libmp4v2-0_1.6dfsg-0.2ubuntu8_amd64.deb


libavcodec53

sudo wget http://free.nchc.org.tw/ubuntu//pool/main/liba/libav/libavcodec53_0.8.10-0ubuntu0.13.10.1_amd64.deb


mpeg4ip-server

sudo wget http://mirror.pnl.gov/ubuntu//pool/multiverse/m/mpeg4ip/mpeg4ip-server_1.6dfsg-0.2ubuntu8_amd64.deb


그리고 다운받은 파일들을 더블클릭해서 설치

중간에 의존성 문제 발생 하면

sudo apt-get -f install 


하지만 mpeg4ip-server는 설치가 안됨 T.T


http://gabrielkim.tistory.com/38   참고해서 어찌저찌 설치 (http://gabrielkim.tistory.com/attachment/cfile5.uf@1264F5474FA386B90BEFCD.deb 다운로드해서 설치)


3. 설치확인


whereis 명령어로 ffmpeg mp4creator faac 확인

하지만 faac는 설치된 경로가 나오지 않음 T.T


http://www.linuxfromscratch.org/blfs/view/svn/multimedia/faac.html 참고해서 faac 설치




여하튼 모두 설치한것 같다. 


4.  air video 설정파일


설정파일 만들고

sudo nano AirVideoServerLinux.properties 


아래의 내용으로 입력

path.ffmpeg = /usr/local/bin/ffmpeg

path.mp4creator = /usr/bin/mp4creator

path.faac = /usr/bin/faac

password =

subtitles.encoding = windows-949

subtitles.font = NanumGothic

folders = Movies:/home/user/media/movies,Drama:/home/user/media/drama   


여기서 각 path와 folder는 자기에게 맞는 걸로 수정


5. 나눔 글꼴 설치


http://hangeul.naver.com/download.nhn#sc_ng 


나눔폰트 모든 OS용으로 다운로드

그리고 다음 명령어로 설치

sudo cp *.ttf /usr/share/fonts/truetype/

sudo fc-cache -v


6. Airvideo AutoStart


nano /etc/init/airvideo.conf


start on runlevel [2345]

stop on shutdown

respawn


exec sudo -H -n -u 사용자계정 LANG=ko_KR.UTF-8 /usr/bin/java -jar /opt/airvideoserver/AirVideoServerLinux.jar /opt/airvideoserver/ffmpeg/AirVideoServerLinux.properties


7. Airvideo Server 수동 실행


sudo start airvideo


(정지는 stop)


8. 공유기 포트포워딩 설정하고 외부에서 DDNS로 접속하니 잘 된다!!! 

하.. 이번거 힘들었다. T.T



내가 유일하게 그리고 정말 유용하게 잘 쓰는 클라우드 서비스는 다음클라우드..

무엇보다 속도도 빠르고 꽤 안정적이다. 게다가 티스토리 이용자 어쩌구 해서 이용가능 용량도 100G이고 :)


여튼 그래서 홈서버에 다음클라우드를 설치하려고 하는데....


기본적으로 다음에서 리눅스 버전도 설치파일을 제공하나 64bit 버전에서는 일련의 작업을 해야한다고 한다.


(참고 : http://ubuntu.or.kr/viewtopic.php?p=90771)


우선 소프트웨어 관리자에서 ia32-libs 를 검색해서 설치 (나는 이미 설치했으므로 설치가 안뜨고 제거가 뜸)





다음에 클라우드 서비스에 들어가면 PC싱크프로그램에서 리눅스용 다운을 받는다. (현재 버전 daumcloud_1.1.0.45_deb)


그리고 다운받은 폴더로 이동한 다음에 아래와 같이 명령


$ mkdir tmp 

$ dpkg-deb -x daumcloud_1.1.0.45.deb tmp 

$ dpkg-deb --control daumcloud_1.1.0.45.deb tmp/DEBIAN 

$ sed -i "s/i386/all/" tmp/DEBIAN/control 

$ dpkg -b tmp daumcloud_1.1.0.45_64.deb


아마 64bit 용 패키지로 만들어 주는 것 같다.

생성된 daumcloud_1.1.0.45_64.deb를 더블클릭해서 설치




그러면 끝! ^-^




이번엔 FTP 설정.. 


이거 해놓고 설마 집에서 일하고 결과물 옮기고 하려는건 아냐?? 


목적은 그런데.. 그렇게 쓰게 되길 없길 ㅋㅋ


감사하게도 같은 환경 (Linux Mint 13 Maya 사용자의 블로그 참조 http://chulhankim.github.io/blog/2014/02/26/linux-mint-13.html


리눅스에서 FTP 서비스로 vsftpd를 많이 쓴다고 한다.


그런데 최신버전의 vsftpd를 apt-get install로는 설치가 불가능 하여 직접 다운로드 하여 설치하는 방법을  사용한다.


디렉토리 이동

cd /home/jslee-server/Downloads


vsftpd 3.0.2 설치파일 다운로드

sudo wget http://us.archive.ubuntu.com/ubuntu/pool/main/v/vsftpd/vsftpd_3.0.2-1ubuntu2_i386.deb

(64bit 버전 사용자는 wget http://us.archive.ubuntu.com/ubuntu/pool/main/v/vsftpd/vsftpd_3.0.2-1ubuntu2_amd64.deb)


설치 (X window 상에서는 더블클릭하면 deb 설치관리자가 뜨고 설치누르면 될꺼임)

sudo dpkg -i vsftpd_3.0.2-1ubuntu2_i386.deb





새로운 사용자를 등록하려면 adduser 명령어 써서 등록하고

난 그냥 혼자 쓸거이므로 따로 안한다.


vsfptd.conf 파일 편집

sudo nano /etc/vsfptd.conf



anonymous_enable=NO

local_enable=YES

write_enable=YES

local_umask=022

chroot_local_user=YES


------------------------------ 여기까지는 코멘트 해제


allow_writeable_chroot=YES

user_config_dir=/etc/vsftpd_user_conf


----------------------------- 여기까지는 마지막 줄에 새로 입력



그리고 /etc/vsftpd_user_conf 생성

nano /etc/vsftpd_user_conf


local_root = /disk/www


하고 저장


나는 루트권한으로로 /disk를 읽을 생각이었는데 이렇게 하면 루트 폴더까지 접근이 되어버린다. 당연한건가? 모르겠슴 ^^;



그리고 윈도우7 컴퓨터에서 파일질라로 접속 시도






잘 된다!! 다만 포트가 22번임에 주의



삼바 설정은 홈서버에서 한번 해봤던걸 기준으로 한다.


그런데 홈서버에서 설정할 때는 smbfs가 안깔리더니 이번에는 또 깔린다.


아마 Linux Mint 버전의 차이인듯.. 


sudo apt-get install samba smbfs 로 samba와 smbfs를 아래와 같이 설치완료





아래와 같이 계정 등록하는 것도 문제 없었슴



자.. 문제는 이제부터

X window가 없으므로 GUI환경이 아닌 콘솔환경에서 삼바 설정을 해야한다..


http://forum.falinux.com/zbxe/index.php?document_srl=405792&mid=lecture_tip  여기서 참조하여 해본다.


smb.conf 편집

sudo nano /etc/samba/smb.conf



security = user 활성

####### Authentication #######

   security = user


계정에 땨르 설정을 다음과 같이

[jslee-server]

comment = jslee-server samba

path = /disk

writeable = yes

public = no

create mask = 0644

directory mode = 0755



지난번 포스팅에 하드디스크 세개를 루트 디렉토리에 각각 /disk150G /disk160G1 /disk160G2 로 마운트했던걸

/disk 밑으로 모두 옮겼슴



그리고 삼바 데몬 리스타트


sudo service smbd restasrt


그리고 윈도우 탐색기에서 \\jslee-server로 접속

더블클릭하면 삼바 유저 아이디 및 패스워드 입력


 

그림처럼 잘 된다!!! ^^


자 그럼 속도는 얼마나 나오나?




45.5MB/S !!! 훌륭하다.. 기존에 Etrayz로 옮길때 10MB/S 정도 였고 자체 하드디스크 내에서 움직여도 45MB/S 정도인데.. (물론 SSD로 옮기면 훨씬 빠르지만)


여튼 충붕히 훌륭하다!!!


이걸로 삼바 설정 끝!!


아.. X window가 뜨면 하드디스크들은 자동으로 마운트 되더만..


Putty로 접속하여 df-a로 확인해보니 부팅 하드만 마운트되어있다.. T.T





자 이제 콘솔모드에서 하드디스크들을 마운트해보자 


일단 하드디스크들이 있긴 한거냐? fdisk -l 해봤다.




보면 sdb가 80G 리눅스가 깔린 디스크이고

sda 250G, sdc 160G, sdd 160G 모두 잘 살아있다. (잘 안쓰이던 하드디스크를 모아서 서버를 만들었더니 갯수만 많다 ㅋ)



구체적인 방법은 여기를 참조했다. (http://koreaubuntu.wordpress.com/2011/12/18/%EB%A6%AC%EB%88%85%EC%8A%A4-%ED%8C%8C%EC%9D%BC-%EC%8B%9C%EC%8A%A4%ED%85%9C%EA%B3%BC-%ED%95%98%EB%93%9C-%EB%A7%88%EC%9A%B4%ED%8A%B8%ED%95%98%EA%B8%B0/)




삽질이 조금 있었... ㅋ

여하튼


 1) ls -l /dev/disk/by-uuid 로 하드디스크의 uuid를 표시하고 복사해두고

 2) 마운트 하고자 하는 하드디스크들이 마운트 될 디렉토리를 만들자 

   나의 경우는 단순 무식하게 일단 /disk250G , /disk160G1 , /disk160G2 로 만들어 두었다.


 3) /etc/fstab 을 편집한다.



정말 이러면 되는 걸까?? 리부팅



그리고 다시 df -a 로 확인!




sda1, sdc1, sdd1 모두 내가 원했던대로 잘 마운트 되었슴!!!

자.. 이제 삼바 설정 해야지 ~

정말 오랜만에 리눅스에 다시 재미붙인듯 ㅋㅋㅋ


뭐 쓸데없이 깨작되는건 아니고


이번엔 회사에서 서버로 쓸 요량이다.


내 프로젝트 파일, 도큐멘트 파일 등을 저장하고 동기화 할 수 있도록 준비하고.


SVN 서버로도 구성하고


뭐 이래저래~


여러 컴퓨터에 여러 파일들이 흩어져 있다보니 가끔 내가 작업은 했는데 어느 컴퓨터에서 했는지 기억도 안나고 T.T 


여튼 그래서 시작!!


1. 우선 Ubuntu 12.04 Server 버전을 설치시도

 -> 실패.. 이유는 모르겠다. grub 설치에 문제가 자꾸 생긴다.


2. 그래서 Linux Mint 13 Maya Mate 32bit 버전 설치하고 Console 모드로 사용

 Linux Mint 설치는 역시 패스.. 윈도우만큼 쉬우니까~!

사실 컴퓨터 사양이 괜찮다면 Xwindow를 버릴 이유는 없는데.. 서버로 쓰려는 컴퓨터가 워낙 구형이다.


Pentium D3.0 (3.0 Ghz)

RAM 1.5G

내장그래픽


* 저 CPU가  어느정도 성능인가 궁금해서 찾아봄 (http://www.cpubenchmark.net/cpu_list.php)


CPU                                    Benchmark Rank         비고

Atom N270 1.6Ghz                 283         1757     구형넷북

Pentium D 3.0Ghz                 648         1404     전에 쓰던 개인 데스크탑

Core 2 Duo E6300 1.86Ghz      1121 1169     회사 데스크탑

1007u 1.5Ghz                         1441 1006         홈서버용

T8300 2.4Ghz                         1481 985         XP전용 랩탑

2030M 2.5Ghz                         2648 616         개인 랩탑

i3-3240 3.4Ghz                        4323 323         현재 개인 데스크탑

i5-4670K 3.4Ghz                      7806 114         회사 개발용 데스크탑



현재 사용하고 있는 컴퓨터들인데.. 역시 Atom이 독보적인 저성능 ㅋㅋ
서버로 쓰고자하는 컴퓨터 역시 안습 T.T


여튼 그래서 과감히 X window는 쓰지 않고 콘솔로만 사용하고자 함!!



3. Linux Mint Console Mode 부팅법

 - 검색해보면 Ubuntu 에 관한것은 상당히 많이 나옴.. Linux Mint가 Ubuntu에서 파생되긴 하였지만 뭐 하려고 하면 다 다르냐 --;;;


 - 다음 링크를 참고하여 겨우 설정했다. (http://forums.linuxmint.com/viewtopic.php?f=42&t=113700)


 1) Mate의 데스크탑인 mdm을 제거

 sudo apt-get purge mdm mint-mdm-themes

 sudo rm -fr /usr/share/mdm


 2) 부트스플래쉬 plymouth 제거

 sudo apt-get purge plymouth-label plymouth-theme-ubuntu-text


 3) /etc/default/grub 파일 수정

GRUB_CMDLINE_LINUX_DEFAULT = "text" 또는 #붙여서 comment 처리

GRUB_GFXMODE = 해상도

#GRUB_HIDDEN_TIMEOUT = 0  comment 처리


 4) grub 업데이트

sudo update-grub2



 이걸로 console 모드 부팅은 완료!!!


그런데 Xwindow 안쓰고 잘 쓸 수 있을까?



아 그리고 서버인 만큼 Puutty로 SSH를 이용해서 원격접속으로 설정을 할 예정




+ Recent posts