|
|
파이썬을 이용한 퀀트 투자 포트폴리오 만들기를 읽었다. 퀀트투자(Quantitative Investing)는 수학, 통계, 데이터 분석, 알고리즘을 활용해 투자 결정을 자동화하는 투자 방식이다. 인간의 감정이나 직관 대신 정량적 데이터와 모델을 기반으로 하여 일관되고 재현 가능한 전략을 만들어내는 것이 특징이다.
# 퀀트투자란?; 데이터(재무제표, 가격, 거래량 등)로부터 규칙을 만들고, 그 규칙에 따라 자동으로 투자하는 시스템 기반 투자 방법.
✔ 특징
* 감정 제거 (공포·탐욕 배제)
* 규칙 기반 → 일관성
* 백테스트 가능
* 대량 데이터 처리
* 자동매매와 연동 쉬움
# 퀀트투자의 주요 전략(핵심 요약)
1) 가치(Value) 전략; 저평가된 기업에 투자
* 저 PER, 저 PBR, 고 배당, EV/EBIT
✔ 예: 마법공식(Magic Formula) (ROIC↑ + PER↓)
2) 모멘텀(Momentum) 전략; 최근에 많이 오른 종목이 앞으로도 강세를 보이는 경향
* 3개월·6개월·12개월 수익률 기준
* 절대 모멘텀(가격이 장기 이동평균 위인지 여부)
3) 퀄리티(Quality) 전략; 재무구조가 우수한 기업 선호
* ROE, ROIC, 영업현금흐름, 부채비율 등
4) 팩터 결합(Multi-factor) 전략; 여러 요인을 조합함
* 가치 + 모멘텀 + 퀄리티 등
* 안정적 수익률 가능
5) 리스크 기반 전략
* 변동성 타기팅
* 최소분산 포트폴리오
* 리스크 패리티(Risk Parity)
# 퀀트투자의 핵심 절차
1. 전략 아이디어 만들기
2. 데이터 수집 (가격, 재무제표 등)
3. 전략 규칙 정의
4. 백테스트(backtest)
5. 성과 분석
6. 실전 운용 (리밸런싱 주기, 거래 비용 고려)
# 퀀트에 필요한 기술(실무 기준)
✔ 필수
* Python (pandas, numpy, yfinance, statsmodels)
* 데이터 분석
* 통계 / 회귀분석 기초
✔ 있으면 좋은 기술
* 머신러닝
* 시계열 분석
* 데이터베이스(SQL/NoSQL)
* 자동매매 시스템 구축
# 파이썬 예시 — *아주 간단한 모멘텀 투자전략*
```python
import yfinance as yf
import pandas as pd
tickers = ["AAPL", "MSFT", "GOOGL", "AMZN"]
data = yf.download(tickers, start="2018-01-01")["Adj Close"]
# 12개월 모멘텀 계산
momentum = data.pct_change(252).iloc[-1]
# 모멘텀 상위 종목 선택
top = momentum.sort_values(ascending=False).head(2)
print("모멘텀 상위 종목:")
print(top)
``` 19
엑셀을 사용해도 되지만 속도나 간편성을 위해 무료로 제공되는 파이썬과 MySQL을 활용하는 것이 장기적으로 더 좋은 방안이다.
1. MySQL이란? 관계형 데이터베이스 관리 시스템(RDBMS)이다. 데이터를 표(테이블) 형태로 저장하고, SQL 언어로 데이터를 관리한다.
* 무료 / 오픈소스
* 웹 서비스, 서버, 기업 시스템에서 많이 사용
* 빠르고 안정적
2. 데이터베이스 기본 구조
```
서버
└ 데이터베이스(Database)
└ 테이블(Table)
└ 행(Row) / 열(Column)
```
* Database: 데이터의 묶음
* Table: 실제 데이터가 저장되는 표
* Row: 한 줄의 데이터
* Column: 데이터의 속성(필드)
3. 기본 SQL 명령어
1) 데이터베이스
```sql
-- 데이터베이스 생성
CREATE DATABASE test_db;
-- 데이터베이스 선택
USE test_db;
-- 데이터베이스 삭제
DROP DATABASE test_db;
```
2) 테이블
```sql
-- 테이블 생성
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50),
age INT,
created_at DATETIME
);
-- 테이블 삭제
DROP TABLE users;
```
3) 데이터 추가 (INSERT)
```sql
INSERT INTO users (name, age, created_at)
VALUES ('홍길동', 25, NOW());
```
4) 데이터 조회 (SELECT)
```sql
-- 전체 조회
SELECT * FROM users;
-- 조건 조회
SELECT name, age FROM users WHERE age >= 20;
```
5) 데이터 수정 (UPDATE)
```sql
UPDATE users
SET age = 26
WHERE name = '홍길동';
```
6) 데이터 삭제 (DELETE)
```sql
DELETE FROM users WHERE name = '홍길동';
```
4. 조건 / 정렬 / 제한
```sql
SELECT * FROM users
WHERE age >= 20
ORDER BY age DESC
LIMIT 5;
```
* `WHERE` : 조건
* `ORDER BY` : 정렬
* `LIMIT` : 개수 제한
5. 주요 데이터 타입
| INT | 정수 |
| VARCHAR(n) | 문자열 |
| TEXT | 긴 문자열 |
| DATE | 날짜 |
| DATETIME | 날짜 + 시간 |
| BOOLEAN | 참/거짓 |
6. 기본 개념 요약
* MySQL은 데이터 저장소
* SQL은 데이터를 다루는 언어
* CRUD; * Create (INSERT) * Read (SELECT) * Update (UPDATE) * Delete (DELETE) 21
변수에서 자주 쓰는 `replace()` 와 `split()` 메서드.
# `replace()` 메서드 (문자열 치환); 문자열에서 특정 문자를 다른 문자로 바꿀 때 사용
### 기본 형태
```python
문자열.replace(바꿀값, 새로운값)
```
### 예제
```python
text = "I like apple"
result = text.replace("apple", "banana")
print(result)
# I like banana
```
### 여러 개 치환
```python
text = "aaa"
print(text.replace("a", "b"))
# bbb
```
### 횟수 제한
```python
text = "one one one"
print(text.replace("one", "two", 2))
# two two one
```
📌 주의: `replace()`는 원본 문자열을 바꾸지 않고, 새 문자열을 반환.
# `split()` 메서드 (문자열 분리); 문자열을 기준 문자로 나누어 리스트로 만듦
### 기본 형태
```python
문자열.split(기준문자)
```
### 예제
```python
text = "apple,banana,orange"
result = text.split(",")
print(result)
# ['apple', 'banana', 'orange']
```
### 공백 기준 분리
```python
text = "Hello Python World"
print(text.split())
# ['Hello', 'Python', 'World']
```
### 최대 분리 횟수
```python
text = "2025-12-14-10-30"
print(text.split("-", 2))
# ['2025', '12', '14-10-30']
```
# `replace()` + `split()` 함께 사용
```python
text = "apple/orange/banana"
result = text.replace("/", ",").split(",")
print(result)
# ['apple', 'orange', 'banana']
```
# 한눈에 정리
| 메서드 | 역할 | 결과 |
| `replace()` | 문자열 치환 | 문자열 |
| `split()` | 문자열 분리 | 리스트 | 29
Python에서 리스트 안에 있는 리스트 요소를 지정(접근)하는 방법.
# 기본 구조
```python
lst = [
[10, 20, 30],
[40, 50, 60],
[70, 80, 90]
]
```
# 리스트의 리스트 요소 접근 (인덱싱)
### 형식
```python
리스트[바깥인덱스][안쪽인덱스]
```
### 예제
```python
print(lst[0]) # [10, 20, 30]
print(lst[0][1]) # 20
print(lst[2][2]) # 90
```
# 요소 값 변경
```python
lst[1][0] = 100
print(lst)
# [[10, 20, 30], [100, 50, 60], [70, 80, 90]]
```
# 음수 인덱스
```python
print(lst[-1]) # [70, 80, 90]
print(lst[-1][-2]) # 80
```
# 반복문으로 접근
1️ 이중 for문
```python
for i in range(len(lst)):
for j in range(len(lst[i])):
print(lst[i][j])
```
2️ 값 기준 (아래 상세 설멸 👍)
```python
for row in lst:
for value in row:
print(value)
```
# 특정 행 / 열 가져오기
### 행(row)
```python
row = lst[1]
print(row) # [40, 50, 60]
```
### 열(column)
```python
col = [row[0] for row in lst]
print(col) # [10, 40, 70]
```
# 슬라이싱
```python
print(lst[0][1:]) # [20, 30]
```
# 한눈에 정리
| 목적 | 방법 |
| 하나의 리스트 접근 | `lst[i]` |
| 리스트 안 값 | `lst[i][j]` |
| 값 변경 | `lst[i][j] = 값` |
| 전체 순회 | 이중 for문 | 31
👍 Python에서 값 기준 반복이란 인덱스(index)를 쓰지 않고, 실제 값(value)을 바로 꺼내서 반복하는 방식.
# 기본 예제 (리스트)
```python
nums = [10, 20, 30]
for x in nums:
print(x)
```
📌 동작 순서
* `nums`에서 값을 하나씩 꺼냄
* `x`에 값이 바로 들어감 → 인덱스를 몰라도 됨
# 인덱스 기준 반복과 비교
### ❌ 인덱스 기준
```python
for i in range(len(nums)):
print(nums[i])
```
### ✅ 값 기준 (추천 👍)
```python
for x in nums:
print(x)
```
✔ 더 짧고
✔ 실수 적고
✔ 가독성 좋음
# 리스트의 리스트에서 값 기준 반복
```python
matrix = [
[1, 2, 3],
[4, 5, 6]
]
for row in matrix:
for value in row:
print(value)
```
* `row` → 안쪽 리스트
* `value` → 실제 값
# 문자열 값 기준 반복
```python
text = "hello"
for ch in text:
print(ch)
```
출력:
```
h
e
l
l
o
```
# 값 변경은 주의 ⚠️
```python
nums = [1, 2, 3]
for x in nums:
x = x * 10
print(nums)
# [1, 2, 3] ← 값 안 바뀜
```
❗ 이유:
* `x`는 복사된 값
* 리스트 요소 자체를 바꾸지 않음
### 값 변경하려면 인덱스 사용
```python
for i in range(len(nums)):
nums[i] *= 10
```
# enumerate (값 + 인덱스 같이)
```python
nums = [10, 20, 30]
for idx, val in enumerate(nums):
print(idx, val)
```
# 한눈에 정리
| 방식 | 특징 |
| 값 기준 | 간단, 읽기 쉬움 |
| 인덱스 기준 | 값 변경 가능 |
| enumerate | 둘 다 필요할 때 | 32
Python에서 datetime(데이트타임) 은 날짜와 시간을 다루는 표준 라이브러리다.
# datetime 모듈 불러오기
```python
from datetime import datetime, date, time, timedelta
```
# 현재 날짜와 시간
```python
now = datetime.now()
print(now)
```
### 날짜만 / 시간만
```python
today = date.today()
current_time = datetime.now().time()
```
# 특정 날짜·시간 만들기
```python
dt = datetime(2025, 12, 14, 10, 30, 0)
print(dt)
```
```python
d = date(2025, 12, 14)
t = time(10, 30)
```
# 날짜·시간 포맷팅 (출력 형식)
### `strftime()` → 문자열로
```python
now = datetime.now()
print(now.strftime("%Y-%m-%d %H:%M:%S"))
```
| 포맷 | 의미 |
| `%Y` | 연도 |
| `%m` | 월 |
| `%d` | 일 |
| `%H` | 시 |
| `%M` | 분 |
| `%S` | 초 |
# 문자열 → datetime
### `strptime()`
```python
text = "2025-12-14 10:30"
dt = datetime.strptime(text, "%Y-%m-%d %H:%M")
```
# 날짜 계산 (`timedelta`)
```python
today = datetime.now()
print(today + timedelta(days=1)) # 내일
print(today - timedelta(days=7)) # 일주일 전
```
# 두 날짜 차이
```python
d1 = datetime(2025, 1, 1)
d2 = datetime(2025, 12, 31)
diff = d2 - d1
print(diff.days) # 일수 차이
```
# 날짜 비교
```python
if d1 < d2:
print("d1이 더 이전")
```
# 자주 쓰는 예제
✔ 현재 시간 기준 로그
```python
print(f"[{datetime.now():%Y-%m-%d %H:%M:%S}] 시작")
```
✔ 생년월일로 나이 계산
```python
birth = datetime(2000, 5, 1)
today = datetime.today()
age = today.year - birth.year
```
# 한눈에 정리
| 현재 시간 | `datetime.now()` |
| 문자열 변환 | `strftime()` |
| 문자열 → 날짜 | `strptime()` |
| 날짜 계산 | `timedelta` | 41
파이썬 반복문을 한 줄로 쓰는 대표적인 방법들
1️ 기본 for 반복문 (리스트 컴프리헨션); [i for i in range(5)]
2️ 조건 있는 반복문; [i for i in range(10) if i % 2 == 0]
3️ 반복하면서 출력; [print(i) for i in range(5)]
4️ 중첩 반복문; [(i, j) for i in range(3) for j in range(3)]
5️ while 느낌의 반복; import itertools; list(itertools.takewhile(lambda x: x < 5, range(10)))
6️ 딕셔너리 반복; {k: v*2 for k, v in {'a':1,'b':2}.items()}
7️ 문자열 반복 처리; [c.upper() for c in "python"] 53
파이썬 람다 함수(lambda) 를 한 줄로 쓰는 대표 예제들 👇
1️ 기본 문법; lambda x: x + 1
2 두 값 계산; lambda x, y: x + y
3 조건문 (삼항 연산); lambda x: "짝수" if x % 2 == 0 else "홀수"
4 정렬 기준; sorted(data, key=lambda x: x[1])
5 map과 함께 사용; list(map(lambda x: x**2, range(5)))
6 filter와 함께 사용; list(filter(lambda x: x % 2 == 0, range(10)))
7 reduce와 함께 사용
from functools import reduce
reduce(lambda a, b: a + b, [1, 2, 3, 4])
8️ 딕셔너리 값 처리; {k: (lambda x: x*2)(v) for k, v in d.items()}
# 람다 함수 주의점
* 한 줄만 가능
* 복잡한 로직 ❌
* 이름 없는 함수 → 간단한 처리용 ✔️ 57
파이썬에서 자주 쓰는 패키지(모듈) 함수 한 줄 예제 👇
## 표준 라이브러리 패키지 함수
1️ `math` (수학)
import math; math.sqrt(16)
import math; math.factorial(5)
2️ `random` (난수)
import random; random.randint(1, 10)
import random; random.choice([1,2,3])
3️ `datetime` (날짜/시간)
from datetime import datetime; datetime.now()
from datetime import date; date.today()
4️ `itertools` (반복자)
import itertools; list(itertools.permutations([1,2,3], 2))
import itertools; list(itertools.combinations([1,2,3], 2))
5️ `collections`
from collections import Counter; Counter("banana")
from collections import deque; deque([1,2,3], maxlen=2)
6️ `functools`
from functools import reduce; reduce(lambda x,y: x+y, [1,2,3])
7️ `os` (시스템)
import os; os.listdir('.')
import os; os.getcwd()
8️ `sys`
import sys; sys.argv
## 외부 패키지 (설치 필요)
9️ `numpy`; import numpy as np; np.mean([1,2,3])
10 `pandas`; import pandas as pd; pd.read_csv('a.csv').head()
외부 패키지를 어디서 찾고 어떻게 고르고 설치하는지.
1️ 패키지는 어디에 있나? → PyPI
### PyPI (Python Package Index)
* 주소: [https://pypi.org](https://pypi.org)
* 파이썬 공식 패키지 저장소
* `pip install` 하면 여기서 자동으로 다운로드
```bash
pip install numpy
```
= PyPI에서 `numpy`를 찾아서 설치
2️ PyPI에서 패키지 찾는 방법
### 방법 1: 웹에서 직접 검색
#1. [https://pypi.org](https://pypi.org) 접속
#2. 상단 검색창에 키워드 입력
예:
* `excel`
* `web`
* `image`
* `crawl`
# 예시
* 엑셀 → `openpyxl`, `pandas`
* 웹 요청 → `requests`
* 크롤링 → `beautifulsoup4`, `selenium`
### 방법 2: 구글 검색 (실무에서 가장 많이 씀)
```
python excel package
python web scraping library
python pdf library
```
➡️ 검색 결과에서 PyPI 링크나 GitHub 확인
3️ 좋은 패키지 고르는 기준 ; PyPI 페이지에서 꼭 확인하세요
### 체크 포인트
* Downloads 많음 (사용자 많음)
* Last release 최근 (관리 중)
* Documentation 있음
* Python version 호환 확인
📌 예:
```
numpy
Downloads: 매우 많음 ✅
Last release: 최근 ✅
Docs 있음 ✅
```
4️ 패키지 사용법은 어디서 보나?
### 1️ PyPI 페이지
* `Description`
* `Usage`
* `Examples`
### 2️ 공식 문서 (Docs)
* PyPI → `Homepage` / `Documentation` 링크
### 3️ GitHub
* `README.md`
* `examples/` 폴더
5️ 찾았으면 설치하기
### PyPI 이름 그대로 설치
```bash
pip install 패키지명
```
⚠️ import 이름이 다를 수 있음
```bash
pip install beautifulsoup4
import bs4
```
6️ 전체 흐름 요약
```
필요한 기능 생각
↓
PyPI / 구글 검색
↓
패키지 비교
↓
pip install
↓
import 해서 사용
```
7️ 초보자에게 추천 패키지 Top 5
| 용도 | 패키지 |
| HTTP 요청 | requests |
| 데이터 | pandas |
| 엑셀 | openpyxl |
| 크롤링 | beautifulsoup4 |
| 자동화 | selenium |
파이썬에서 매소드(Method)와 함수(Function)의 차이는 주로 속성과 사용 위치에 있다.
1. 함수 (Function)
* 정의: 함수는 특정 작업을 수행하는 코드 블록. `def` 키워드를 사용하여 정의.
* 특징: 함수는 일반적으로 독립적으로 존재하며, 객체에 속하지 않는다.
* 사용 예: 다른 함수나 클래스 외부에서 사용할 수 있다.
```python
def greet(name):
return f"Hello, {name}!"
print(greet("Alice")) # "Hello, Alice!"
```
2. 매소드 (Method)
* 정의: 매소드는 클래스 안에서 정의된 함수. 객체(인스턴스)에서 호출되며, 해당 객체를 첫 번째 인수로 받는다. 보통 첫 번째 인수로 `self`를 사용.
* 특징: 매소드는 클래스의 인스턴스에 연결되어 있으며, 해당 인스턴스의 속성이나 다른 메소드에 접근할 수 있다.
* 사용 예: 클래스 내에서 객체와 관련된 작업을 수행할 때 사용.
```python
class Greeter:
def __init__(self, name):
self.name = name
def greet(self):
return f"Hello, {self.name}!"
g = Greeter("Bob")
print(g.greet()) # "Hello, Bob!"
```
# 차이점 요약
* 함수는 독립적으로 존재하는 코드 블록으로, 특정 객체에 종속되지 않는다.
* 매소드는 클래스 안에 정의된 함수로, 클래스의 인스턴스에서 호출되며, 해당 인스턴스를 첫 번째 인수로 받는다 (보통 `self`).
# 예시로 이해하기
```python
# 함수
def add(a, b):
return a + b
# 클래스와 매소드
class Calculator:
def add(self, a, b):
return a + b
# 함수 사용
result = add(3, 4) # 7
# 매소드 사용
calc = Calculator()
result = calc.add(3, 4) # 7
```
이처럼, 함수는 클래스 외부에서 사용되는 반면, 매소드는 클래스 내부에서 객체와 함께 사용되는 차이가 있다. 63
`시리즈(Series)`와 `데이터프레임(DataFrame)`은 파이썬의 Pandas 라이브러리에서 자주 사용되는 두 가지 주요 데이터 구조다.
1. 시리즈 (Series); `시리즈`는 1차원 배열과 비슷하며, 인덱스(index)와 값(values)로 이루어져 있다. 하나의 컬럼처럼 생각할 수 있는데, 각 값에 접근할 수 있는 인덱스가 붙어 있다.
* 1차원 배열 구조.
* 인덱스와 값으로 구성.
* 동일한 데이터 타입.
#### 예시:
```python
import pandas as pd
# 리스트로 시리즈 생성
s = pd.Series([10, 20, 30, 40])
print(s)
```
출력:
```
0 10
1 20
2 30
3 40
dtype: int64
```
#### 인덱스를 직접 지정할 수도 있다:
```python
s = pd.Series([10, 20, 30, 40], index=['a', 'b', 'c', 'd'])
print(s)
```
출력:
```
a 10
b 20
c 30
d 40
dtype: int64
```
2. 데이터프레임 (DataFrame); `데이터프레임`은 2차원 구조로, 여러 개의 시리즈(컬럼)가 모여 있는 형태다. 테이블 형태로 생각하면 된다. 각 컬럼은 시리즈로, 행은 데이터의 레코드(row)다.
* 2차원 배열 구조.
* 여러 시리즈(컬럼)를 가질 수 있다.
* 각 컬럼은 서로 다른 데이터 타입을 가질 수 있다.
* 인덱스와 컬럼명이 각각 존재.
#### 예시:
```python
# 딕셔너리로 데이터프레임 생성
data = {
'A': [1, 2, 3],
'B': [4, 5, 6],
'C': [7, 8, 9]
}
df = pd.DataFrame(data)
print(df)
```
출력:
```
A B C
0 1 4 7
1 2 5 8
2 3 6 9
```
### 시리즈와 데이터프레임의 차이점:
* 차원: 시리즈는 1차원, 데이터프레임은 2차원.
* 구성 요소: 시리즈는 값만 가지고 있고, 데이터프레임은 여러 시리즈로 구성
* 사용 목적: 시리즈는 주로 하나의 컬럼 데이터를 다룰 때 사용하고, 데이터프레임은 여러 컬럼을 포함하는 데이터를 다룰 때 사용. 65
파이썬에서 데이터 재구조화는 보통 `pandas` 라이브러리를 사용한다.
1️ 기본 준비
```python
import pandas as pd
```
2️ 행 ↔ 열 변환 (가장 많이 쓰임)
### pivot (행 → 열)
```python
df.pivot(index='날짜', columns='상품', values='판매량')
```
### pivot_table (집계 가능)
```python
pd.pivot_table(
df,
index='날짜',
columns='상품',
values='판매량',
aggfunc='sum'
)
```
3️ 열 → 행 (melt)
```python
pd.melt(
df,
id_vars=['날짜'],
value_vars=['사과', '바나나'],
var_name='상품',
value_name='판매량'
)
```
4️ 데이터 병합
### 가로 병합 (join / merge)
```python
pd.merge(df1, df2, on='id', how='inner')
```
* `how='left' | 'right' | 'outer'`
### 세로 병합 (concat)
```python
pd.concat([df1, df2], axis=0)
```
5️ 그룹화 후 구조 변경
```python
df.groupby('카테고리')['매출'].sum().reset_index()
```
6️ 컬럼 분리 / 결합
### 컬럼 분리
```python
df[['년', '월']] = df['날짜'].str.split('-', expand=True)
```
### 컬럼 결합
```python
df['날짜'] = df['년'] + '-' + df['월']
```
7️ JSON / 중첩 데이터 평탄화
```python
pd.json_normalize(data)
```
8️ 인덱스 재구조화
```python
df.set_index('id')
df.reset_index()
```
✔️ 가장 많이 쓰는 조합
* `groupby + agg`
* `pivot_table`
* `melt`
* `merge`
## 📊 예제 데이터 (판매 데이터)
```python
import pandas as pd
data = {
'날짜': ['2024-01-01', '2024-01-01', '2024-01-02', '2024-01-02'],
'상품': ['사과', '바나나', '사과', '바나나'],
'판매량': [10, 5, 7, 8],
'매출': [10000, 5000, 7000, 8000]
}
df = pd.DataFrame(data)
df
```
### 원본 데이터 구조
| 날짜 | 상품 | 판매량 | 매출 |
| 2024-01-01 | 사과 | 10 | 10000 |
| 2024-01-01 | 바나나 | 5 | 5000 |
| 2024-01-02 | 사과 | 7 | 7000 |
| 2024-01-02 | 바나나 | 8 | 8000 |
1️ 분석하기 좋은 구조로 변경 (Pivot) 👉 **날짜별 · 상품별 판매량**
```python
pivot_df = df.pivot(
index='날짜',
columns='상품',
values='판매량'
)
pivot_df
```
### 결과
| 날짜 | 사과 | 바나나 |
| 2024-01-01 | 10 | 5 |
| 2024-01-02 | 7 | 8 |
2️ 집계 포함 재구조화 (pivot_table) 👉 **날짜별 상품 판매량 합계**
```python
pivot_table_df = pd.pivot_table(
df,
index='날짜',
columns='상품',
values='판매량',
aggfunc='sum'
)
pivot_table_df
```
3️ 머신러닝/저장용 구조로 되돌리기 (Melt)
```python
melt_df = pd.melt(
pivot_df.reset_index(),
id_vars='날짜',
var_name='상품',
value_name='판매량'
)
melt_df
```
4️ 그룹화 후 구조 단순화 👉 **날짜별 총매출**
```python
daily_sales = (
df.groupby('날짜')['매출']
.sum()
.reset_index()
)
daily_sales
```
5️ 컬럼 추가 (재구조화 응용) 👉 **단가 컬럼 생성**
```python
df['단가'] = df['매출'] / df['판매량']
df
```
## 🔄 재구조화 전 vs 후 정리
| 목적 | 사용 함수 |
| 행 → 열 | `pivot`, `pivot_table` |
| 열 → 행 | `melt` |
| 집계 | `groupby + agg` |
| 구조 단순화 | `reset_index` |
## 🎯 실무에서 이렇게 씀
* 리포트용 → `pivot_table`
* 머신러닝 → `melt + 정규화`
* DB 저장 → `groupby 후 단순 테이블` 103
데이터베이스는 테이블로 이루어지고 우선 테이블을 만들고 열이름과 데이터형태, 제약을 지정하고 이 형식에 맞게 행을 입력한다. 그리고 테이블로 부터(from) 열의 일부나 전부(select), 혹은 조건에 맞는 행만 선택(where)하여 활용가능하다. 151
파이썬에서 MySQL에 연결하는 표준적인 방법: 실무에서 바로 쓸 수 있게 설치 → 연결 → CRUD → 주의사항순서로 정리.
1️ 라이브러리 설치 - 가장 많이 쓰는 라이브러리: PyMySQL
```bash
pip install pymysql
```
(대안: `mysql-connector-python`)
2️ MySQL 연결 기본 코드
```python
import pymysql
conn = pymysql.connect(
host="localhost", # MySQL 서버 주소
user="root", # 사용자명
password="password", # 비밀번호
database="test_db", # DB 이름
port=3306,
charset="utf8mb4",
cursorclass=pymysql.cursors.DictCursor
)
print("연결 성공")
```
3️ 커서 사용 & SQL 실행
### 🔹 SELECT (조회)
```python
with conn.cursor() as cur:
sql = "SELECT * FROM users"
cur.execute(sql)
rows = cur.fetchall()
print(rows)
```
### 🔹 INSERT (추가)
```python
with conn.cursor() as cur:
sql = "INSERT INTO users (name, age) VALUES (%s, %s)"
cur.execute(sql, ("Alice", 30))
conn.commit()
```
### 🔹 UPDATE (수정)
```python
with conn.cursor() as cur:
sql = "UPDATE users SET age=%s WHERE name=%s"
cur.execute(sql, (31, "Alice"))
conn.commit()
```
### 🔹 DELETE (삭제)
```python
with conn.cursor() as cur:
sql = "DELETE FROM users WHERE name=%s"
cur.execute(sql, ("Alice",))
conn.commit()
```
4️ 테이블 생성 예제
```python
with conn.cursor() as cur:
cur.execute("""
CREATE TABLE IF NOT EXISTS users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50),
age INT
)
""")
conn.commit()
```
5️ 연결 종료 (중요)
```python
conn.close()
```
6️ 에러 처리 (실무 필수)
```python
try:
conn = pymysql.connect(...)
with conn.cursor() as cur:
cur.execute("SELECT 1")
except pymysql.MySQLError as e:
print("DB 에러:", e)
finally:
conn.close()
```
7️ SQL Injection 방지 (❗중요)
❌ 잘못된 예:
```python
cur.execute(f"SELECT * FROM users WHERE name='{name}'")
```
✅ 올바른 예:
```python
cur.execute(
"SELECT * FROM users WHERE name=%s",
(name,)
)
```
8️ MySQL Connector 방식 (공식 드라이버)
```bash
pip install mysql-connector-python
```
```python
import mysql.connector
conn = mysql.connector.connect(
host="localhost",
user="root",
password="password",
database="test_db"
)
```
9️ SQLAlchemy로 MySQL 연결 (추천)
```bash
pip install sqlalchemy pymysql
```
```python
from sqlalchemy import create_engine
engine = create_engine(
"mysql+pymysql://root:password@localhost:3306/test_db"
)
with engine.connect() as conn:
result = conn.execute("SELECT * FROM users")
print(result.fetchall())
```
## 어떤 방법이 좋을까?
| 목적 | 추천 |
| 간단한 스크립트 | PyMySQL |
| 공식 지원 | mysql-connector |
| 실무 / 대규모 | SQLAlchemy | 188
아스키 코드(ASCII Code) 는 문자를 숫자로 표현하는 가장 기본적인 문자 인코딩 방식.
1️ 아스키 코드란?
* ASCII = American Standard Code for Information Interchange
* 컴퓨터가 문자(영문, 숫자, 기호)를 처리하기 위해 만든 표준
* 0 ~ 127 (7비트) 총 128개 문자
2️ 아스키 코드 구조
### 🔹 제어 문자 (0~31, 127)
* 화면에 출력되지 않음
* 예: 줄바꿈, 탭 등
| 값 | 의미 |
| 10 | LF (줄바꿈 `\n`) |
| 9 | TAB (`\t`) |
| 0 | NULL |
| 27 | ESC |
### 🔹 출력 가능 문자 (32~126)
| 문자 | ASCII |
| (공백) | 32 |
| 0 | 48 |
| 9 | 57 |
| A | 65 |
| Z | 90 |
| a | 97 |
| z | 122 |
| ! | 33 |
| @ | 64 |
📌 규칙
* 숫자 `'0'`은 48부터 시작
* 대문자 A–Z → 65–90
* 소문자 a–z → 97–122
3️ 파이썬에서 아스키 코드 사용
```python
ord('A') # 65
ord('a') # 97
chr(65) # 'A'
chr(97) # 'a'
```
4️ 대소문자 변환 원리
```python
ord('a') - ord('A') # 32
```
➡️ 대문자 ↔ 소문자 차이는 **32**
5️ 아스키 코드 예시 표 (자주 쓰는 것)
```
A 65 a 97
B 66 b 98
C 67 c 99
0 48 1 49
! 33 ? 63
```
6️ 아스키 vs 유니코드
| 구분 | ASCII | Unicode |
| 문자 수 | 128개 | 140,000+ |
| 한글 | ❌ | ✅ |
| 이모지 | ❌ | ✅ |
| 호환성 | 매우 높음 | ASCII 포함 |
📌 ASCII는 Unicode의 부분집합
7️ 언제 쓰이나?
* 문자열 처리 알고리즘
* 암호화 / 인코딩 학습
* 대소문자 계산
* C, Python 기초 학습
UTF-8은 현재 전 세계에서 가장 널리 쓰이는 문자 인코딩 방식.
ASCII의 한계를 확장해 모든 문자(한글, 한자, 이모지 등)를 표현.
1️ UTF-8이란?
* UTF = Unicode Transformation Format
* 가변 길이 인코딩 (1~4바이트)
* ASCII와 100% 호환
2️ 바이트 구조
| 문자 종류 | 바이트 수 |
| ASCII (영문, 숫자) | 1바이트 |
| 유럽 문자 | 2바이트 |
| 한글 | 3바이트 |
| 이모지 | 4바이트 |
예:
```text
A → 41 (1 byte)
가 → EA B0 80 (3 bytes)
😀 → F0 9F 98 80 (4 bytes)
```
3️ UTF-8 vs ASCII
| 구분 | ASCII | UTF-8 |
| 문자 수 | 128 | 전 세계 문자 |
| 한글 | ❌ | ✅ |
| 가변 길이 | ❌ | ✅ |
| 호환성 | – | ASCII 완전 포함 |
📌 ASCII 문서는 그대로 UTF-8 문서로 읽힘
4️ 파이썬에서 UTF-8 다루기
### 🔹 문자열 → 바이트
```python
s = "한글"
b = s.encode("utf-8")
print(b)
```
### 🔹 바이트 → 문자열
```python
b = b'\xed\x95\x9c\xea\xb8\x80'
s = b.decode("utf-8")
print(s)
```
5️ UTF-8 깨짐(모지바케) 원인
* 인코딩 ≠ 디코딩
* UTF-8로 저장 → EUC-KR로 열기 등
📌 해결:
* 저장/읽기 항상 UTF-8 통일
* Python:
```python
open("test.txt", encoding="utf-8")
```
6️ 왜 UTF-8이 표준이 됐나?
✅ 전 세계 문자 지원
✅ 저장 공간 효율적
✅ ASCII 호환
✅ 웹·DB·OS 표준
> HTML, JSON, Python, Linux, macOS 기본 인코딩 = UTF-8 189
CSS는 웹페이지의 디자인과 레이아웃을 담당하는 언어.
HTML이 “뼈대”라면, CSS는 “옷과 스타일”.
1️ CSS란?
* Cascading Style Sheets
* 글자 색, 크기, 위치, 애니메이션까지 담당
* HTML과 분리해서 관리 → 유지보수 쉬움
2️ CSS 기본 문법
```css
선택자 {
속성: 값;
}
```
예:
```css
p {
color: blue;
font-size: 16px;
}
```
3️ CSS 적용 방법
### 🔹 1. 인라인
```html
<p style="color:red;">Hello</p>
```
### 🔹 2. 내부 스타일
```html
<style>
p { color: red; }
</style>
```
### 🔹 3. 외부 스타일 (권장)
```html
<link rel="stylesheet" href="style.css">
```
4️ 선택자(Selector)
| 종류 | 예시 |
| 태그 | `p` |
| 클래스 | `.box` |
| 아이디 | `#header` |
| 자식 | `div > p` |
| 후손 | `div p` |
| 속성 | `input[type="text"]` |
5️ 자주 쓰는 속성
### 🎨 텍스트
```css
color: red;
font-size: 16px;
font-weight: bold;
text-align: center;
```
📦 박스 모델
```css
width: 200px;
margin: 10px;
padding: 20px;
border: 1px solid black;
```
6️ 레이아웃 핵심
### 🔹 Flexbox (가장 많이 사용)
```css
.container {
display: flex;
justify-content: center;
align-items: center;
}
```
### 🔹 Grid (복잡한 레이아웃)
```css
.container {
display: grid;
grid-template-columns: repeat(3, 1fr);
}
```
7️ 반응형 디자인
```css
@media (max-width: 768px) {
body {
background: lightgray;
}
}
```
8️ CSS 우선순위
1. `!important`
2. 인라인
3. ID
4. Class
5. Tag 199
크롤링(웹 크롤링) 은 웹페이지에서 자동으로 데이터를 수집하는 기술. 보통 파이썬으로 가장 많이 한다.
1️ 크롤링 vs 스크래핑
* 크롤링: 여러 페이지를 돌아다니며 수집
* 스크래핑: 특정 페이지에서 필요한 정보만 추출 (일반적으로 둘을 섞어서 말함)
2️ 크롤링 기본 구조
```text
요청(Request) → HTML 수신 → 파싱 → 데이터 추출 → 저장
```
3️ 파이썬 크롤링 기본 (정적 페이지)
### 📦 라이브러리 설치
```bash
pip install requests beautifulsoup4
```
### 🔎 예제
```python
import requests
from bs4 import BeautifulSoup
url = "https://example.com"
res = requests.get(url)
res.raise_for_status()
soup = BeautifulSoup(res.text, "html.parser")
title = soup.find("h1").text
print(title)
```
4️ CSS Selector 사용
```python
soup.select("div.article > h2")
soup.select_one("#content")
```
5️ 동적 페이지 크롤링 (JavaScript); `requests`로 안 될 때 사용
### 🔹 Selenium
```bash
pip install selenium
```
```python
from selenium import webdriver
driver = webdriver.Chrome()
driver.get("https://example.com")
print(driver.page_source)
driver.quit()
```
6️ 데이터 저장
### 📄 CSV
```python
import csv
with open("data.csv", "w", newline="", encoding="utf-8") as f:
writer = csv.writer(f)
writer.writerow(["title"])
writer.writerow([title])
```
### 🗄 DB (MySQL)
```python
# 크롤링 → DB 저장 가능
```
7️ 크롤링 시 주의사항 ⚠️ (중요)
* `robots.txt` 확인
* 과도한 요청 ❌ (딜레이 필수)
* 로그인 / 개인정보 수집 ❌
* 상업적 사용 주의 (법적 문제)
```python
import time
time.sleep(1)
```
8️ 자주 막히는 경우
| 문제 | 해결 |
| 403 에러 | User-Agent 설정 |
| 데이터 없음 | JS 렌더링 → Selenium |
| IP 차단 | 요청 간격 늘리기 |
```python
headers = {
"User-Agent": "Mozilla/5.0"
}
requests.get(url, headers=headers)
```
9️ 실무 추천 스택
| 목적 | 도구 |
| 간단 | requests + BS |
| 대규모 | Scrapy |
| 동적 페이지 | Selenium / Playwright | 205
BeautifulSoup은 파이썬에서 HTML/XML을 파싱해서 원하는 데이터만 뽑아내는 라이브러리. 웹 크롤링/스크래핑의 핵심 도구
1️ BeautifulSoup이란?
* HTML 문서를 트리 구조로 변환
* 태그, 클래스, id로 쉽게 탐색
* `requests`와 함께 가장 많이 사용
2️ 설치
```bash
pip install beautifulsoup4
```
(보통 같이 설치)
```bash
pip install requests
```
3️ 기본 사용 예제
```python
import requests
from bs4 import BeautifulSoup
url = "https://example.com"
res = requests.get(url)
res.raise_for_status()
soup = BeautifulSoup(res.text, "html.parser")
print(soup.title.text)
```
4️ 요소 찾기
### 🔹 하나 찾기
```python
soup.find("h1")
soup.find("div", class_="content")
```
### 🔹 여러 개 찾기
```python
soup.find_all("p")
```
5️ CSS Selector (가장 많이 씀)
```python
soup.select("div.article > h2")
soup.select_one("#main")
```
예:
```python
titles = soup.select(".news-title")
for t in titles:
print(t.text.strip())
```
6️ 속성(Attribute) 가져오기
```python
link = soup.find("a")
print(link["href"])
```
7️ 텍스트만 깔끔하게
```python
tag.text
tag.get_text(strip=True)
```
8️ 실무에서 자주 막히는 문제
### ❗ 데이터가 안 나올 때
* JavaScript로 로딩되는 페이지
→ ❌ BeautifulSoup 불가
→ ✅ Selenium / Playwright 사용
### ❗ 403 에러
```python
headers = {
"User-Agent": "Mozilla/5.0"
}
requests.get(url, headers=headers)
```
9️ BeautifulSoup은 언제 쓰나?
| 상황 | 사용 |
| 정적 HTML | ✅ 최고 |
| 빠른 파싱 | ✅ |
| JS 렌더링 | ❌ |
| 대규모 크롤링 | Scrapy | 206
동적 크롤링은 자바스크립트(JS)로 콘텐츠가 동적으로 로드되는 웹페이지를 수집하는 방법. 일반적인 `requests + BeautifulSoup` 방식으로는 데이터가 안 보일 때 사용.
## 왜 필요한가?
* 페이지 로드 후 AJAX/Fetch/XHR로 데이터가 추가됨
* 무한 스크롤, 버튼 클릭 후 로딩, SPA(React/Vue) 구조
* 초기 HTML에 원하는 데이터가 없음
## 주요 방법 3가지
1️ 브라우저 자동화 (가장 직관적)
* Selenium, Playwright, Puppeteer
* 실제 브라우저처럼 JS 실행 → 화면에 보이는 그대로 수집
* 👍 성공률 높음 / 👎 느림, 리소스 큼
**언제 쓰나?**
* 로그인 필요
* 클릭/스크롤/대기 로직이 복잡할 때
2️ 네트워크(API) 직접 호출 (가장 효율적 ⭐)
* 개발자도구 → Network → XHR/Fetch 분석
* 실제로 데이터를 주는 백엔드 API를 직접 호출
**언제 쓰나?**
* 데이터 API가 노출되어 있을 때
* 대량 수집, 속도 중요
3️ 하이브리드
* 브라우저로 토큰/쿠키만 획득
* 이후 `requests`로 API 반복 호출
## 간단 예시 (Playwright, Python)
```python
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(headless=True)
page = browser.new_page()
page.goto("https://example.com")
page.wait_for_selector(".item") # 동적 로딩 대기
items = page.query_selector_all(".item")
for i in items:
print(i.inner_text())
browser.close()
```
## 주의사항 ⚠️
* robots.txt / 서비스 약관 확인
* 과도한 요청 → IP 차단
* 로그인/토큰 사용 시 보안 유의
* 상업적 사용은 법적 이슈 가능
## 선택 가이드
| 상황 | 추천 |
| 화면에 보이는 그대로 필요 | Selenium / Playwright |
| JSON 데이터만 필요 | API 직접 호출 |
| 속도·대량 수집 | API 방식 |
| 로그인 후 데이터 | 하이브리드 | 238
https://product.kyobobook.co.kr/detail/S000200883665
머리말 xi 이 책에 대하여 xii 추천사 xiv
PART I 퀀트와 프로그래밍 기초 배워 보기
CHAPTER 1 퀀트에 대해 알아보기 3 1.1 퀀트 투자의 핵심 재료, 데이터 4 1.2 퀀트 투자에 프로그래밍이 필요한 이유 4 1.3 최고의 인기 언어, 파이썬 5 1.4 데이터 관리의 표준, SQL 6
CHAPTER 2 파이썬 기초 배워 보기 8 2.1 상수와 변수 8 2.2 데이터 타입 9 2.3 제어문 30 2.4 함수 39 2.5 패키지 사용하기 41
CHAPTER 3 데이터 분석 배워 보기 48 3.1 시리즈 48 3.2 데이터프레임 52 3.3 데이터 불러오기 및 저장하기 60 3.4 데이터 요약 정보 및 통곗값 살펴보기 62 3.5 결측치 처리하기 67 3.6 인덱스 다루기 72 3.7 필터링 74 3.8 새로운 열 만들기 78 3.9 데이터프레임 합치기 80 3.10 데이터 재구조화 88 3.11 데이터프레임에 함수 적용하기 93 3.12 그룹 연산하기 96 3.13 시계열 데이터 다루기 103
CHAPTER 4 데이터 시각화 배워 보기 110 4.1 그래프의 구성 요소 110 4.2 matplotlib 패키지를 이용한 시각화 111 4.3 pandas 패키지를 이용한 시각화 117 4.4 seaborn 패키지를 이용한 시각화 121
CHAPTER 5 SQL 기초 배워 보기 128 5.1 데이터베이스와 테이블 만들기 128 5.2 SQL 기초 구문 익히기 133 5.3 연산자 135 5.4 집약 함수 137 5.5 그룹화와 정렬 139 5.6 뷰와 서브쿼리 141 5.7 함수, 술어와 case 식 144 5.8 테이블의 집합과 결합 151 5.9 SQL 고급 처리 156
CHAPTER 6 파이썬에서 SQL 연결하기 161 6.1 파이썬에서 SQL DB에 접속하기 161 6.2 pandas를 이용한 데이터 읽기 및 쓰기 163 6.3 upsert 기능 구현하기 165
PART II 크롤링을 이용한 데이터 수집
CHAPTER 7 크롤링을 위한 웹 기본 지식 173 7.1 인코딩에 대한 이해 173 7.2 웹의 동작 방식 175 7.3 HTML과 CSS 176
CHAPTER 8 정적 크롤링 실습 187 8.1 GET과 POST 방식 이해하기 187 8.2 크롤링 예제 190
CHAPTER 9 동적 크롤링과 정규 표현식 204 9.1 동적 크롤링이란? 204 9.2 정규 표현식 216
CHAPTER 10 국내 주식 데이터 수집 223 10.1 최근 영업일 기준 데이터 받기 223 10.2 한국거래소의 업종분류 현황 및 개별지표 크롤링 224 10.3 WICS 기준 섹터 정보 크롤링 235 10.4 수정주가 크롤링 240 10.5 재무제표 크롤링 247 10.6 가치지표 계산 256
CHAPTER 11 전 세계 주식 데이터 수집 264 11.1 유료 데이터 벤더 이용하기 265 11.2 티커 수집하기 270 11.3 주가 다운로드 279 11.4 재무제표 다운로드 283
CHAPTER 12 투자 참고용 데이터 수집 288 12.1 DART의 Open API를 이용한 데이터 수집하기 288 12.2 FRED 데이터 다운로드 297 12.3 Fear & Greed Index 301
PART III 포트폴리오 구성, 백테스트 및 매매하기
CHAPTER 13 퀀트 전략을 이용한 종목 선정 307 13.1 팩터 이해하기 308 13.2 베타 이해하기 308 13.3 밸류 전략 312 13.4 모멘텀 전략 322 13.5 퀄리티 전략 331 13.6 마법 공식 337 13.7 섹터 중립 포트폴리오 346 13.8 이상치 데이터 처리 및 팩터의 결합 349 13.9 멀티팩터 포트폴리오 354
CHAPTER 14 포트폴리오 구성 전략 367 14.1 수익률 계산 및 상관관계 확인하기 368 14.2 최대샤프지수 포트폴리오 369 14.3 최소분산 포트폴리오 372 14.4 위험균형 포트폴리오 380
CHAPTER 15 트레이딩을 위한 기술적 지표 385 15.1 TA-Lib 패키지 설치하기 385 15.2 이동평균 387 15.3 상대강도지수 389 15.4 볼린저 밴드 391
CHAPTER 16 백테스팅 시뮬레이션 393 16.1 bt 패키지 394 16.2 정적 자산배분: 올웨더 포트폴리오 401 16.3 동적 자산배분 403 16.4 추세추종 전략 백테스트 407 16.5 평균회귀 전략 백테스트 415 16.6 bt 패키지의 함수 419
CHAPTER 17 증권사 API 연결과 매매하기 421 17.1 모의투자 및 API 서비스 신청하기 423 17.2 접근 토큰 및 해시키 발급받기 427 17.3 주식 현재가 시세 조회하기 429 17.4 주식 주문하기 430 17.5 주식 잔고조회 436 17.6 스케줄링 438 17.7 포트폴리오 리밸런싱 441
APPENDIXA 파이썬 다운로드 및 설치하기 460 아나콘다 설치하기 460 스파이더 사용하기 465
APPENDIXB SQL 다운로드 및 설치하기 467
찾아보기 482
