1. 들어가며
1) 파이썬으로 주식코드를 만들고 3가지 정보를 받으려고,
파이참에서 실행(shift + f10)했는데, 1가지 정보만 받아왔다.
2) 이유는, 파이썬의 GIL(Global Interpreter Lock) 때문이며,
파이썬 인터프리터는 한 스레드에서 하나의 코드를 실행시킬 수 있도록 해주기 때문이다.
- 예를 들어, 즉, a함수가 1분마다 실행되고 있다면, 이 경우 b,c 함수는 미실행된다
* a함수는 1분마다 1분봉 받기,
b는 5초마다 현재가 받기, c는 5초마다 매수가 받기 함수
2. 접근 방법
ㅇ 파이썬의 GIL을 우회하는 방법(병렬 처리)으로 검색을 해보니,
라이브러리 중 asyncio, multithreading, multiprocessing 등 3가지를 알아보았다.
- asyncio : 함수 앞에 일일히 asyncio를 붙이고, 전달변수 앞에 await를 붙이는 등
코드 변경이 심한거 같음 → 미채택
- multithreading : 리스트 threads를 만들어 주어야 하고, target을 넣어주는 등 불편하고,
time.sleep(1)를 넣어주는 등 시간 소요 → 미채택
- multiprocessing : 코드의 변경이 심하지 않고, 직관적으로 1줄씩만 넣어주면 됨 → 채택
3. 기타 사항
1) 인터넷 검색으로는 다중처리 라이브러리에 대해 소요되는 시간에 중점을 두고 설명하지만,
이 글에서는 "소요시간"보다는 다중처리 실행할 수 있는지에 대해 설명 예정
2) 파이썬 3.9.12 기준으로 작성하였으며, 아래 출처에 있는 내용을 코드로 구현하여 실행
* 출처 : https://docs.python.org/ko/3/library/multiprocessing.html
4. 단일 프로세스가 적용
1) 단일 프로세스 코드 : if __name__ == '___main__ ':
아래에 함수 2줄(AAA.f(), AAA.g())이 단일 프로세스를 활용하는 코드이다.
# from multiprocessing import Process
import os
# import threading
class AAA():
def f():
print(1 + 2)
print(os.getpid())
# threading.Timer(3, AAA.f).start()
def g():
print(3 + 4)
print(os.getpid( ))
# threading.Timer(6, AAA.g).start()
if __name__ == '__main__':
AAA.f()
AAA.g()
2) 단일 프로세스 적용 화면 → 프로세스 주소가 "10712"로 고정
5. 코드 작성 과정 (다중 병렬 처리 적용)
1) 라이브러리 2개를 불러온다.
- 다중처리를 위한 multiprocessing와 Process ID를 구하기 위해 os모듈을 활용한다.
(둘다 python 내장함수)
from multiprocessing import Process
import os
# import threading
2) 주식시스템의 구현을 위해 1개의 클래스 안에 2개의 함수를 구현한다.
* threading.Timer(3, AAA.f).start() → 3초마다 f함수를 실행
class AAA():
def f():
print(1 + 2)
print(os.getpid())
# threading.Timer(3, AAA.f).start()
def g():
print(3 + 4)
print(os.getpid( ))
# threading.Timer(6, AAA.g).start()
3) 실행 파일에는 Process를 설정하고, 시작(start)해 주고,
프로세스가 종료될때까지 block해주는 join함수를 넣어준다.
* 필자는 1분마다 1분봉 받는 함수를 장중 내내 실행시키기 위해,
join은 프로세스가 작업을 완료하고 종료될때까지 기다릴 때 사용하는 명령어이다.
if __name__ == '__main__':
p = Process(target=AAA.f,)
q = Process(target=AAA.g,)
p.start()
# p.join()
q.start()
# q.join()
6. 전체 코드
ㅇ 3초~6초마다 f함수와 g함수를 실행하고 싶으면, 아래의 3가지 주석 해제
* 3번줄(import)및 9번줄(timer), 14번줄(timer) 주석 해제
from multiprocessing import Process
import os
# import threading
class AAA():
def f():
print(1 + 2)
print(os.getpid())
# threading.Timer(3, AAA.f).start()
def g():
print(3 + 4)
print(os.getpid( ))
# threading.Timer(6, AAA.g).start()
if __name__ == '__main__':
p = Process(target=AAA.f,)
q = Process(target=AAA.g,)
p.start()
# p.join()
q.start()
# q.join()
7. 코드 결과
ㅇ 2개 프로세스 주소 : f함수 실행 결과 4532(프로세스 주소),
g함수 실행결과 3196(프로세스 주소)가 출력됨
→ 즉, 2개 프로세스를 활용한다.
8. 마무리
ㅇ 간단한 코드는 다중처리(다른 프로세스 주소)가 실행되는 모습을 보았다.
동 내용을 주식 시스템의 소스코드에 적용하여 다중처리가 된다면,
좀 더 빠른 연산속도와 파이썬의 GIL을 일부나마 우회할 수 있지 않을까 생각된다.
'1. 국내주식 > 1-1. 국내주식 연구일지' 카테고리의 다른 글
(파이썬) 주식 자동 매매를 위한 알고리즘 패턴 찾기 (1) 엑셀 이용 (2) | 2022.10.02 |
---|---|
(파이썬) pandas와 os모듈을 활용하여 데이터를 엑셀로 보내기 (2) | 2022.09.30 |
(주식 자동매매) 키움증권 영웅문4에서 1분봉 엑셀로 받는 방법 (0) | 2022.09.29 |
(파이썬) threading와 time 모듈로 특정 시간마다 반복 실행 (0) | 2022.09.24 |
(파이썬) for문 활용 (2) - zip()함수 (0) | 2022.09.19 |
(파이썬) for문 활용 (1) - 기본 설명 (2) | 2022.09.16 |
(파이썬) 주식 자동매매를 위한 사전준비 (필요 모듈) (0) | 2022.09.15 |
(잡담) 국내주식 시스템 만드는 현황 ('22.5.29 현재) (0) | 2022.05.29 |