ํ‹ฐ์Šคํ† ๋ฆฌ ๋ทฐ

๋ฐ˜์‘ํ˜•

๐Ÿ“Š ํ€€ํŠธ ํˆฌ์ž ๋ฆฌํฌํŠธ ์ž๋™ ์ƒ์„ฑ ์‹œ์Šคํ…œ – Python์œผ๋กœ PDF ๋ณด๊ณ ์„œ ๋งŒ๋“ค๊ธฐ

ํ€€ํŠธ ํˆฌ์ž์—์„œ “๋ฐ์ดํ„ฐ๋กœ ํŒ๋‹จํ•œ๋‹ค”๋Š” ๊ฑด ๊ฒฐ๊ตญ
๊ฒฐ๊ณผ๋ฅผ ๊ธฐ๋กํ•˜๊ณ , ๋น„๊ตํ•˜๊ณ , ์‹œ๊ฐํ™”ํ•œ๋‹ค๋Š” ๋œป์ž…๋‹ˆ๋‹ค.

์ด๋ฒˆ ๊ธ€์—์„œ๋Š” ์•ž์„œ ๋งŒ๋“  ์ž๋™ ๋ฆฌ๋ฐธ๋Ÿฐ์‹ฑ ์‹œ์Šคํ…œ์—
PDF ๋ฆฌํฌํŠธ ์ž๋™ ์ƒ์„ฑ ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

์ฆ‰, ๋งค์›” ๋ง ์ž๋™์œผ๋กœ ์•„๋ž˜ ๋‚ด์šฉ์„ ํฌํ•จํ•œ ํˆฌ์ž ๋ฆฌํฌํŠธ๊ฐ€ PDF๋กœ ์ €์žฅ๋ฉ๋‹ˆ๋‹ค.

โœ… ์ด๋ฒˆ ๋‹ฌ ์ˆ˜์ต๋ฅ  ๊ทธ๋ž˜ํ”„
โœ… ํฌํŠธํด๋ฆฌ์˜ค ๊ตฌ์„ฑ
โœ… ์ฃผ์š” ํŒฉํ„ฐ ์ ์ˆ˜
โœ… ๋ˆ„์  ์ˆ˜์ต๋ฅ  ๋ฐ MDD
โœ… ๋‹ค์Œ ๋ฆฌ๋ฐธ๋Ÿฐ์‹ฑ ์ผ์ •


1๏ธโƒฃ ์„ค์น˜ ์ค€๋น„

pip install reportlab matplotlib pandas

์ด ์„ธ ๊ฐ€์ง€๋ฉด ์ถฉ๋ถ„ํ•ฉ๋‹ˆ๋‹ค.

  • reportlab: PDF ํŒŒ์ผ ์ƒ์„ฑ
  • matplotlib: ์ˆ˜์ต๋ฅ  ์ฐจํŠธ
  • pandas: ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ

2๏ธโƒฃ ๊ธฐ๋ณธ ์ฝ”๋“œ ๊ตฌ์กฐ

๋ฐ˜์‘ํ˜•
import pandas as pd
import matplotlib.pyplot as plt
from reportlab.lib.pagesizes import A4
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Image
from reportlab.lib.styles import getSampleStyleSheet
from datetime import datetime

# ์˜ˆ์‹œ ๋ฐ์ดํ„ฐ
portfolio = pd.DataFrame({
    "Ticker": ["005930.KS", "000660.KS", "035420.KS"],
    "Return": [0.052, 0.034, 0.071],
    "Score": [0.78, 0.66, 0.83]
})

# ์ˆ˜์ต๋ฅ  ๊ทธ๋ž˜ํ”„
plt.figure(figsize=(6, 3))
portfolio["Return"].plot(kind="bar", color="skyblue")
plt.title("Monthly Returns by Stock")
plt.ylabel("Return (%)")
plt.tight_layout()
plt.savefig("returns_chart.png")
plt.close()

# PDF ์ƒ์„ฑ
styles = getSampleStyleSheet()
doc = SimpleDocTemplate(f"Quant_Report_{datetime.now().strftime('%Y%m')}.pdf", pagesize=A4)
elements = []

elements.append(Paragraph("๐Ÿ“Š Quant Investment Monthly Report", styles['Title']))
elements.append(Spacer(1, 12))
elements.append(Paragraph(f"Report Date: {datetime.now().strftime('%Y-%m-%d')}", styles['Normal']))
elements.append(Spacer(1, 12))

elements.append(Paragraph("<b>1๏ธโƒฃ Portfolio Overview</b>", styles['Heading2']))
elements.append(Paragraph(portfolio.to_html(index=False), styles['Normal']))
elements.append(Spacer(1, 12))

elements.append(Paragraph("<b>2๏ธโƒฃ Monthly Return Chart</b>", styles['Heading2']))
elements.append(Image("returns_chart.png", width=400, height=200))
elements.append(Spacer(1, 12))

elements.append(Paragraph("<b>3๏ธโƒฃ Key Indicators</b>", styles['Heading2']))
elements.append(Paragraph("MDD: -6.2%<br/>Sharpe Ratio: 1.34<br/>Next Rebalancing: 2025-11-01", styles['Normal']))

doc.build(elements)
print("โœ… PDF ๋ฆฌํฌํŠธ ์ƒ์„ฑ ์™„๋ฃŒ")

3๏ธโƒฃ ์‹คํ–‰ ๊ฒฐ๊ณผ

์ด ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜๋ฉด
๐Ÿ“„ Quant_Report_202510.pdf ๊ฐ™์€ ํŒŒ์ผ์ด ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.

๋ฆฌํฌํŠธ ์•ˆ์—๋Š” ๋‹ค์Œ ํ•ญ๋ชฉ์ด ์ž๋™์œผ๋กœ ํฌํ•จ๋ฉ๋‹ˆ๋‹ค:

ํ•ญ๋ชฉ ์„ค๋ช…

ํฌํŠธํด๋ฆฌ์˜ค ํ‘œ ์ข…๋ชฉ๋ช…, ์ˆ˜์ต๋ฅ , ํŒฉํ„ฐ ์ ์ˆ˜
์ˆ˜์ต๋ฅ  ๊ทธ๋ž˜ํ”„ ์›”๊ฐ„ ์„ฑ๊ณผ ๋น„๊ต ์‹œ๊ฐํ™”
ํ•ต์‹ฌ ์ง€ํ‘œ MDD, ์ƒคํ”„์ง€์ˆ˜, ๋ฆฌ๋ฐธ๋Ÿฐ์‹ฑ ์ผ์ •

๐Ÿ’ก ๋””์ž์ธ์„ ์ข€ ๋” ๊ณ ๊ธ‰์Šค๋Ÿฝ๊ฒŒ ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด reportlab.platypus.Table์ด๋‚˜
matplotlib.style.use("ggplot")์„ ์ถ”๊ฐ€ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.


4๏ธโƒฃ ์ž๋™ํ™”์™€ ์—ฐ๊ฒฐํ•˜๊ธฐ

์•ž์„œ ๋งŒ๋“  **๋ฆฌ๋ฐธ๋Ÿฐ์‹ฑ ์Šค์ผ€์ค„๋Ÿฌ ์ฝ”๋“œ(schedule ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ)**์™€ ๊ฒฐํ•ฉํ•˜๋ฉด
๋งค์›” ๋งˆ์ง€๋ง‰ ๋‚  ์ž๋™์œผ๋กœ PDF ๋ณด๊ณ ์„œ๊ฐ€ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.

import schedule, time
schedule.every().month.at("18:00").do(generate_report)
while True:
    schedule.run_pending()
    time.sleep(60)

์ด์ œ ์™„์ „ํžˆ ์ž๋™ํ™”๋œ “ํ€€ํŠธ ๋ฆฌํฌํŠธ ์‹œ์Šคํ…œ”์ด ์™„์„ฑ๋ฉ๋‹ˆ๋‹ค.


5๏ธโƒฃ ํ™•์žฅ ์•„์ด๋””์–ด

ํ™•์žฅ ๊ธฐ๋Šฅ ์„ค๋ช…

๐Ÿ’ฌ Slack/Email ์•Œ๋ฆผ ์ƒ์„ฑ๋œ PDF ์ž๋™ ์ „์†ก
โ˜๏ธ Google Drive ์—…๋กœ๋“œ ํด๋ผ์šฐ๋“œ ๋ณด๊ด€ ๋ฐ ๊ณต์œ 
๐Ÿ“ˆ Multi-Factor Summary ํŒฉํ„ฐ๋ณ„ Score ํ‰๊ท  ์ž๋™ ํ‘œ๊ธฐ
๐Ÿงฎ Benchmark ๋น„๊ต KOSPI·S&P500 ๋Œ€๋น„ ์ˆ˜์ต๋ฅ  ์ฐจํŠธ

๐Ÿ“Œ ์ •๋ฆฌ

๋‹จ๊ณ„ ๊ธฐ๋Šฅ ์„ค๋ช…

1 ์ˆ˜์ต๋ฅ  ๋ฐ์ดํ„ฐ ์ˆ˜์ง‘ yfinance, pandas
2 ๊ทธ๋ž˜ํ”„ ์ƒ์„ฑ matplotlib
3 PDF ๋ฆฌํฌํŠธ ์ƒ์„ฑ reportlab
4 ์ž๋™ํ™” schedule ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๊ฒฐํ•ฉ
5 ๊ณต์œ  Google Drive or Email ์—ฐ๋™

๐Ÿ‘‰ ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์—ฌ๋Ÿฌ๋ถ„์€ ์›”๊ฐ„ ํ€€ํŠธ ์šด์šฉ ๋ฆฌํฌํŠธ๋ฅผ ํด๋ฆญ ํ•œ ๋ฒˆ ์—†์ด ์ž๋™์œผ๋กœ ๋ฐ›์•„๋ณด๋Š” ์‹œ์Šคํ…œ์„ ๊ฐ–๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.


๐Ÿ“˜ ๋‹ค์Œ ๊ธ€ ์˜ˆ๊ณ 

๋‹ค์Œ ํŽธ์—์„œ๋Š” **“ํ€€ํŠธ ์ „๋žต ์ตœ์ ํ™” – ๋ฐฑํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๊ฐ€์ค‘์น˜ ์ž๋™ ์กฐ์ •ํ•˜๊ธฐ”**๋ฅผ ๋‹ค๋ฃน๋‹ˆ๋‹ค.
์ฆ‰, ๊ฐ ํŒฉํ„ฐ์˜ ์„ฑ๊ณผ์— ๋”ฐ๋ผ ํฌํŠธํด๋ฆฌ์˜ค ๋น„์ค‘์„ ์ž๋™์œผ๋กœ ์—…๋ฐ์ดํŠธํ•˜๋Š” ‘AIํ˜• ํ€€ํŠธ ์‹œ์Šคํ…œ’์„ ๋งŒ๋“ค์–ด๋ณผ ๊ฑฐ์˜ˆ์š”.


๐Ÿ”– ์ถ”์ฒœ ํƒœ๊ทธ (SEO ์ตœ์ ํ™”์šฉ)

ํ€€ํŠธ์ž๋™ํ™”,PDF๋ฆฌํฌํŠธ,ํŒŒ์ด์ฌ๋ฆฌํฌํŠธ,reportlab,matplotlib,ํ€€ํŠธํˆฌ์ž,์ฃผ์‹๋ฐ์ดํ„ฐ์‹œ๊ฐํ™”,์ž๋™๋ฆฌ๋ฐธ๋Ÿฐ์‹ฑ,ํˆฌ์ž๋ฆฌํฌํŠธ,ํŒŒ์ด์ฌ์ž๋™ํ™”


 

โ€ป ์ด ํฌ์ŠคํŒ…์€ ์ฟ ํŒก ํŒŒํŠธ๋„ˆ์Šค ํ™œ๋™์˜ ์ผํ™˜์œผ๋กœ, ์ด์— ๋”ฐ๋ฅธ ์ผ์ •์•ก์˜ ์ˆ˜์ˆ˜๋ฃŒ๋ฅผ ์ œ๊ณต๋ฐ›์Šต๋‹ˆ๋‹ค.
๊ณต์ง€์‚ฌํ•ญ
์ตœ๊ทผ์— ์˜ฌ๋ผ์˜จ ๊ธ€
์ตœ๊ทผ์— ๋‹ฌ๋ฆฐ ๋Œ“๊ธ€
Total
Today
Yesterday
๋งํฌ
ยซ   2026/02   ยป
์ผ ์›” ํ™” ์ˆ˜ ๋ชฉ ๊ธˆ ํ† 
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
๊ธ€ ๋ณด๊ด€ํ•จ
๋ฐ˜์‘ํ˜•