Open Net Worth
Open Net Worth는 직접 운영하는 오픈소스 개인 AI 자산 비서로, 전체 재무를 하나의 원장에 기록하고 사용자가 제어하는 AI가 관리
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
📈 Rich Stock — 주식 자동 수집 · 조회 시스템 코스피 · 코스닥 전 종목(일반주식 + ETF)과 이름 있는 미국 종목 100여 개의 시세 · 투자지표 · 재무지표를 자동으로 모아서 웹 화면으로 조회하는 개인용 시스템입니다. 시세와 재무는 완전히 분리되어 있습니다. 한쪽이 고장 나도 다른 쪽과 화면은 정상 동작합니다. 한국 시세를 야후로 바꾸지 않은 이유 야후는 한국 종목의 PER·PBR·EPS·배당수익률을 날짜별로 주지 않습니다. 화면의 숫자와 업종 견주기가 전부 그 값으로 돌아가고 있어서, 갈아타면 통째로 사라집니다. 야후는 pykrx 가 아예 못 주는 것(미국 종목·지수·환율)만 맡습니다. 미국 종목의 돈 단위 daily_price.close 는 늘 원입니다 — 미국 종목은 그날 환율로 바꿔 넣습니다 (시가총액 줄세우기·모의투자가 한 단위로 돌아가야 하기 때문). 손대지 않은 달러 값은 close_local 에 함께 들어갑니다. 화면은 달러를 크게 보여주고 원화 어림값을 밑에 붙이며, 등락률·수익률·차트는 달러 기준입니다 (원화로 재면 환율 움직임이 섞여 회사의 성과가 흐려집니다).README 전문 보기 ↗
코스피 · 코스닥 전 종목(일반주식 + ETF)과 이름 있는 미국 종목 100여 개의 시세 · 투자지표 · 재무지표를 자동으로 모아서 웹 화면으로 조회하는 개인용 시스템입니다.
[한국 시세] 한국거래소 ─┐
[한국 재무] DART 공시 ─┼→ 데이터베이스 → 화면(Next.js)
[미국·지수] 야후 파이낸스 ┘
한국 시세 : 매일 밤 11시 자동 수집 (GitHub Actions)
미국 시세 : 매일 오후 4시 자동 수집 (GitHub Actions)
한국 재무 : 분기마다 자동 수집 (GitHub Actions)
시세와 재무는 완전히 분리되어 있습니다. 한쪽이 고장 나도 다른 쪽과 화면은 정상 동작합니다.
| 구분 | 출처 | 항목 | 갱신 주기 |
|---|---|---|---|
| 한국 시세 | 한국거래소 (pykrx) | 종가·등락률·거래량·시가총액 | 매일 |
| 한국 투자지표 | 한국거래소 (pykrx) | PER·PBR·EPS·BPS·배당수익률 | 매일 |
| 한국 재무지표 | DART 전자공시 | ROE·부채비율·영업이익률·배당성향 | 분기 |
| 미국 시세·지표 | 야후 파이낸스 (yfinance) | 종가·거래량·PER·PBR·배당·ROE·부채비율 | 매일 |
| 지수·환율 | 야후 파이낸스 (yfinance) | 코스피·코스닥·나스닥·S&P500·원달러 | 매일 |
한국 시세를 야후로 바꾸지 않은 이유 야후는 한국 종목의 PER·PBR·EPS·배당수익률을 날짜별로 주지 않습니다. 화면의 숫자와 업종 견주기가 전부 그 값으로 돌아가고 있어서, 갈아타면 통째로 사라집니다. 야후는 pykrx 가 아예 못 주는 것(미국 종목·지수·환율)만 맡습니다.
미국 종목의 돈 단위
daily_price.close 는 늘 원입니다 — 미국 종목은 그날 환율로 바꿔 넣습니다
(시가총액 줄세우기·모의투자가 한 단위로 돌아가야 하기 때문). 손대지 않은
달러 값은 close_local 에 함께 들어갑니다. 화면은 달러를 크게 보여주고
원화 어림값을 밑에 붙이며, 등락률·수익률·차트는 달러 기준입니다
(원화로 재면 환율 움직임이 섞여 회사의 성과가 흐려집니다).
| 무엇 | 어디서 | 비고 |
|---|---|---|
| Neon 계정 | https://neon.tech | 데이터 저장 창고. 무료 |
| 한국거래소 계정 | https://data.krx.co.kr | 시세 조회에 필요. 무료 |
| DART 인증키 | https://opendart.fss.or.kr | 재무지표에만 필요. 무료 · 선택 |
DART 는 없어도 됩니다. 시세·투자지표·화면은 DART 없이 전부 동작하고, 재무지표(ROE·부채비율 등) 칸만 비어 있게 됩니다.
⚠️ 한국거래소는 2025년부터 시세 데이터 조회에 회원 로그인을 요구합니다. 로그인 없이 요청하면 서버가 거부합니다. 우회 방법은 없으니 무료 가입이 필요합니다.
프로젝트 폴더에서 명령창(PowerShell)을 열고:
copy .env.example .env
notepad .env
메모장이 열리면 세 곳을 본인 값으로 바꾸고 저장합니다.
DATABASE_URL=postgresql://... ← Neon 대시보드에서 복사
KRX_ID=내아이디 ← data.krx.co.kr 아이디
KRX_PW=내비밀번호 ← data.krx.co.kr 비밀번호
DART_API_KEY=40자리인증키 ← opendart.fss.or.kr (선택)
.env파일은.gitignore에 등록되어 있어 깃허브에 절대 올라가지 않습니다.
py -m venv .venv
.venv\Scripts\python.exe -m pip install -r requirements.txt
.venv\Scripts\python.exe -m src.check
네 항목이 모두 정상 으로 나와야 다음으로 넘어갈 수 있습니다.
.venv\Scripts\python.exe -m src.create_tables
보통은 손으로 하지 않아도 됩니다.
src/create_tables.py가 바뀐 채로 깃허브main에 올라가면.github/workflows/setup.yml이 저절로 돌아서 없는 표를 만들어 둡니다. 위 명령은 내 컴퓨터에서 시험해 볼 때만 쓰면 됩니다.급할 땐 깃허브 > Actions > 표 만들기 (자동) > Run workflow 로 아무 때나 직접 돌릴 수도 있습니다.
여러 번 돌려도 안전합니다. 모두
CREATE TABLE IF NOT EXISTS라서 이미 있는 표와 그 안의 자료는 건드리지 않습니다.
깃허브에서 돌리는 편이 편합니다. Actions → 과거 시세 채우기 → Run workflow 를 누르면 됩니다. 내 컴퓨터를 켜두지 않아도 되고, 인터넷이 끊겨도 상관없습니다. 데이터베이스를 새로 만들었을 때(예: 다른 곳으로 이사) 여기서 채우세요.
중간에 멈춰도 괜찮습니다. 받은 날짜를 적어두기 때문에 다시 누르면 못 받은 날부터 이어서 받습니다.
내 컴퓨터에서 직접 돌리려면:
.venv\Scripts\python.exe -m src.backfill
.venv\Scripts\python.exe -m src.backfill --years 1.venv\Scripts\python.exe -m src.daily_collect
.venv\Scripts\python.exe -m src.dart_corpcode
.venv\Scripts\python.exe -m src.financial_collect --years 3 --skip-dividend
--skip-dividend 를 빼면 배당성향까지 받지만 API 호출이 약 8,000건 늘고
1시간 이상 걸립니다. 나중에 따로 받아도 됩니다.호출 아끼는 법: 회사를 100곳씩 묶어서 요청합니다. 한 곳씩 부르면 2,650곳 × 12분기 = 31,800건으로 하루 한도(20,000건)를 넘습니다.
.venv\Scripts\python.exe -m src.backfill_fundamental
⚠️ 284만 행에 지표를 채우면 100MB 이상 늘어 Neon 무료 한도(512MB)를 넘길 수 있습니다. 화면은 최신 PER/PBR 만 쓰므로 굳이 필요 없습니다.
화면은 web/ 안의 Next.js 이고 Vercel 에 올라가 있습니다. 휴대폰에서
바로 열면 됩니다.
내 컴퓨터에서 고쳐 보려면:
cd web
npm install
npm run dev
.env.local 에 DATABASE_URL 을 넣어야 시세가 보입니다.
끄려면 명령창에서 Ctrl+C.
예전에는 Streamlit 화면(
app.py)도 함께 있었습니다. 휴대폰으로만 쓰게 되면서 걷어냈습니다 — 고칠 때마다 같은 것을 두 곳에 해야 했고, Streamlit 쪽은 아무도 열지 않았습니다. 코드는 깃 기록에 남아 있습니다.
기능
수익률은 외부에서 받아오는 값이 아니라, 데이터베이스에 쌓인 과거 종가로 직접 계산합니다.
(최근 종가 ÷ N개월 전 종가 − 1) × 100
.github/workflows/daily.yml 이 매일 한국시간 밤 11시에 src.daily_collect 를
자동 실행합니다. 내 컴퓨터가 꺼져 있어도 동작합니다.
| Name | Secret | 쓰이는 곳 |
|---|---|---|
DATABASE_URL | Neon 연결 문자열 | 매일 + 분기 |
KRX_ID | 한국거래소 아이디 | 매일 (시세) |
KRX_PW | 한국거래소 비밀번호 | 매일 (시세) |
DART_API_KEY | DART 40자리 인증키 | 분기 (재무) |
워크플로우는 서로 독립적입니다.
| 파일 | 언제 | 무엇을 |
|---|---|---|
daily.yml | 매일 밤 11시(KST) | 한국 시세 + PER/PBR |
us.yml | 매일 오후 4시(KST) | 미국 시세 + 지수·환율 |
quarterly.yml | 2·5·8·11월 15일 새벽 3시 | DART 재무지표 |
us.yml 은 열쇠가 필요 없습니다(야후는 무료·무인증). 처음 한 번만
Actions → 미국 시세 수집 → Run workflow 에서 days 에 365 를 넣어
1년치를 채우면, 그다음부터는 매일 최근 며칠만 덧댑니다.
한쪽이 실패해도 다른 쪽은 그대로 돕니다.
Actions 탭 → 왼쪽에서 매일 시세 수집 선택 → 우측 Run workflow 버튼으로 지금 바로 시험 실행할 수 있습니다.
프레임워크(Framework Preset)를 반드시 Next.js 로 두세요.
이 저장소는 뿌리에 파이썬(src/, requirements.txt)이 있고 화면은
web/ 안의 Next.js 입니다. Vercel 에 프로젝트를 새로 연결하면 뿌리를
먼저 보고 파이썬 프로젝트로 자동 인식하는 일이 생깁니다.
그러면 아주 헷갈리는 방식으로 실패합니다.
빌드는 web/package.json 을 보고 next build 를 제대로 돌려서
끝까지 성공합니다. 로그에 빨간 줄이 하나도 없습니다.
그런데 결과물을 올리는 단계에서는 프로젝트 설정(python) 을 보고 파이썬식 경로를 기대합니다. Next.js 결과물이 안 맞으니 거절합니다.
errorCode : invalid_routes errorStep : process-and-upload-routes
빌드 로그만 보면 멀쩡해서 원인을 찾는 데 한참 걸립니다. 실제로 이것 때문에 배포가 여러 번 막혔습니다. 설정 위치는
Vercel > 프로젝트 > Settings > Build and Deployment > Framework Settings
Root Directory 는 web, Framework 는 Next.js 입니다.
(web/vercel.json 의 "framework": "nextjs" 는 빌드에만 쓰이고
프로젝트 설정을 덮어쓰지 않습니다)
| 파일 | 역할 |
|---|---|
.env | 비밀 정보 (깃허브에 안 올라감) |
.env.example | .env 작성 견본 |
requirements.txt | 필요한 부품 목록 |
src/config.py | 비밀값 읽기 |
src/db.py | 데이터베이스 접속 |
src/create_tables.py | 표 만들기 (1회) |
src/krx.py | 거래소에서 데이터 받기 (로그인 · 재시도 · 분할요청) |
src/store.py | 받은 데이터 저장 (중복 방지) |
src/update_tickers.py | 종목 목록 갱신 |
src/backfill.py | 과거 3년치 시세 채우기 (1회, 이어받기 지원) |
src/backfill_fundamental.py | 과거 PER/PBR 채우기 (선택) |
src/daily_collect.py | 매일 수집 (한국 시세 + 투자지표) |
src/yahoo.py | 야후 파이낸스에서 받기 (묶어 부르기 · 재시도 · 단위 정리) |
src/us_list.py | 담을 미국 종목 목록 (여기만 고치면 됩니다) |
src/us_collect.py | 미국 시세·지수·환율 수집 (원화 환산 포함) |
src/dart.py | DART 오픈API 접속 담당 |
src/dart_corpcode.py | 종목코드 ↔ DART 회사코드 대응표 |
src/financial_collect.py | 재무지표 수집 (분기 1회) |
src/check.py | 설정 점검 도구 |
src/disclosure.py | 공시 분류 (회사가 어디로 가는지) |
src/disclosure_collect.py | 공시 모으기 |
.github/workflows/setup.yml | 표가 바뀌면 자동으로 만들기 |
.github/workflows/backfill.yml | 과거 시세 채우기 (누를 때만) |
.github/workflows/daily.yml | 매일 시세 자동 실행 |
.github/workflows/quarterly.yml | 분기별 재무 자동 실행 |
ticker — 종목 목록
| 칸 | 설명 |
|---|---|
code | 종목코드 (기본키) |
name | 종목명 |
market | KOSPI / KOSDAQ |
kind | STOCK / ETF |
is_active | 상장중 여부 (상장폐지 시 FALSE) |
first_seen / last_seen | 최초/최종 확인일 |
daily_price — 일별 시세
| 칸 | 설명 |
|---|---|
code + trade_date | 기본키 (중복 저장 불가) |
close | 종가 |
change_pct | 등락률 (%) |
volume | 거래량 |
market_cap | 시가총액 |
일별시세 표에는 투자지표 칸도 함께 있습니다:
per, pbr, eps, bps, div_yield, dps (ETF 는 거래소가 주지 않아 빈칸)
financial — 재무지표 (DART)
| 칸 | 설명 | 계산식 |
|---|---|---|
code+fiscal_year+fiscal_quarter | 기본키 (중복 저장 불가) | — |
roe | 자기자본이익률 (%) | 당기순이익 ÷ 자본총계 × 100 |
debt_ratio | 부채비율 (%) | 부채총계 ÷ 자본총계 × 100 |
op_margin | 영업이익률 (%) | 영업이익 ÷ 매출액 × 100 |
payout_ratio | 배당성향 (%) | 현금배당금총액 ÷ 당기순이익 × 100 |
revenue 외 | 계산에 쓴 원본 금액 (검산용) | DART 원본 |
분기 번호: 1=1분기 2=반기 3=3분기 4=사업보고서(연간)
ingest_log / dart_log — 수집 진행 기록 (이어받기용)
재무제표는 이미 지나간 일입니다. 회사가 앞으로 뭘 하려는지는 공시에 먼저 나옵니다. 신규시설투자·타법인취득·공급계약·유상증자 같은 것들입니다.
.venv\Scripts\python.exe -m src.create_tables # 공시 표 만들기
.venv\Scripts\python.exe -m src.dart_corpcode # 종목↔DART 번호 잇기 (이미 했다면 건너뛰기)
.venv\Scripts\python.exe -m src.disclosure_collect --days 365
마지막 줄이 최근 1년치 공시를 받아옵니다. 몇 분 걸립니다.
깃허브가 매일 밤 11시 30분에 알아서 받습니다.
(.github/workflows/disclosure.yml, DART_API_KEY 가 등록되어 있어야 합니다)
직접 받고 싶으면:
.venv\Scripts\python.exe -m src.disclosure_collect # 최근 7일치
종목마다 따로 부르지 않고 '이 기간 공시 전부' 를 100건씩 받습니다. 하루치가 보통 1,000건 안팎이라 코스피·코스닥 합쳐 20~30번이면 끝납니다. DART 하루 한도는 20,000건이라 여유가 많습니다.
대시보드의 🧭 방향 탭에서 봅니다. 공시를 여섯 갈래로 나눠 보여줍니다.
| 갈래 | 뜻 |
|---|---|
| ⚠️ 조심할 일 | 횡령·소송·감사의견 등. 원문을 꼭 읽어보세요 |
| 🏭 돈을 씁니다 | 신규시설투자·타법인취득. 사업을 키우려는 움직임 |
| 📄 일감을 땄습니다 | 판매·공급계약. 앞으로 매출이 될 것 |
| 💰 돈을 구합니다 | 유상증자·전환사채. 내 지분이 묽어집니다 |
| 🎁 주주에게 돌려줍니다 | 배당·자기주식 취득 |
| 👤 주인이 바뀝니다 | 최대주주 변경·대량보유 |
⚠️ 제목만 보고 나눈 것입니다. 같은 '유상증자' 라도 공장을 지으려는 것이면 좋은 신호, 빚을 막으려는 것이면 나쁜 신호입니다. 어느 쪽인지는 DART 원문을 읽어야 알 수 있어서, 화면에서 원문으로 바로 갈 수 있게 했습니다.
💰 모의투자 화면은 가짜 돈으로 수익을 내보는 곳이 아닙니다. 몇 번 안 되는 매매에서 수익률은 거의 운입니다. 운은 다음에 또 오지 않지만, 판단하는 습관은 실제 돈을 넣어도 그대로 따라옵니다. 그래서 이 화면은 수익률 대신 습관을 봅니다.
| 탭 | 하는 일 |
|---|---|
| 🎓 연습 | 무엇부터 해볼지(8단계) · 내 판단 습관 점수 · 지금 고칠 것 하나 |
| 💼 내 계좌 | 지금 들고 있는 것 · 목표가/손절가 도달 알림 |
| 🛒 사고팔기 | 사고파는 곳. 살 때 이유의 '종류' 를 함께 고릅니다 |
| 🔍 복기 | 판 뒤에 '계획대로 했는지' 되짚기 · 이유 종류별 성적 |
| 💵 예수금 | 연습에 쓸 돈 넣기/빼기 |
| 항목 | 무엇을 보나 |
|---|---|
| 살 이유를 적는가 | 이유를 적고 산 비율 |
| 팔 기준을 미리 정하는가 | 목표가·손절가를 사기 전에 정한 비율 |
| 정한 기준을 지키는가 | 정해둔 대로 판 비율 |
| 오래 들고 있는가 | 평균 보유일 (30일이면 만점) |
| 나눠 담는가 | 가장 큰 한 종목의 비중 |
| 비용을 아끼는가 | 수수료·세금이 넣은 돈의 몇 %를 먹었는지 |
비용은 '사고판 금액' 이 아니라 '넣은 돈' 대비로 잽니다. 사고판 금액 대비로 재면 한 번을 사고팔든 백 번을 사고팔든 비율이 똑같이 나와서, 자주 사고파는 버릇이 전혀 드러나지 않기 때문입니다.
| 판정 | 언제 |
|---|---|
| ✅ 목표를 지켰습니다 | 정한 목표가 이상에서 팔았을 때 |
| ✅ 손절을 지켰습니다 | 정한 손절가 근처에서 팔았을 때 |
| ✅ 이유가 사라져 팔았습니다 | 가격이 아니라 회사를 보고 팔았을 때 |
| ⚠️ 손절이 늦었습니다 | 손절가보다 5% 이상 더 내려간 뒤 팔았을 때 |
| ⚠️ 목표 전에 팔았습니다 | 이익이 났는데 목표 전에 서둘러 팔았을 때 |
| ⚠️ 손절 전에 팔았습니다 | 손절가에 닿기도 전에 불안해서 팔았을 때 |
| ⚠️ 기준 없이 팔았습니다 | 목표가·손절가를 아예 안 정했을 때 |
돈을 벌었는지로 판정하지 않습니다. 계획대로 손절했는데 그 뒤에 오를 수도 있고, 아무 생각 없이 샀는데 운 좋게 오를 수도 있습니다. 결과에는 운이 섞이지만 과정은 내 것이라 다음에도 똑같이 반복됩니다.
살 때 고른 이유(실적이 좋아서 / 값이 싸 보여서 / 뉴스·테마를 보고 / 그냥 느낌으로 …)를 종류별로 모아 승률과 손익 합계를 보여줍니다. "뉴스 보고 산 것은 늘 잃는다" 같은 사실이 숫자로 드러나는 곳이라, 이 화면에서 가장 값진 부분입니다. (3번 미만은 운일 가능성이 커서 참고만)
이유의 종류는
paper_trade.reason칸에[종류] 메모형태로 함께 저장합니다. 표를 새로 만들지 않아도 되고, 사람이 읽어도 그대로 읽힙니다.
ETF 는 시가총액이 빈칸입니다.
한국거래소가 ETF 스냅샷으로 주는 항목은 NAV, 시가, 고가, 저가, 종가, 거래량, 거래대금, 기초지수 뿐이고 시가총액이 없습니다. ETF 규모는 거래대금으로 보세요.
ETF 등락률은 직접 계산합니다. 거래소가 ETF 등락률을 주지 않아서, 바로 전 거래일 종가와 비교해 계산합니다. 단, 앞뒤 날짜가 7일 넘게 벌어져 있으면(데이터가 아직 안 채워진 구간 등) 엉뚱한 값이 들어가지 않도록 비워 둡니다.
적자 기업의 PER 은 빈칸입니다.
거래소는 적자 기업 PER 을 0 으로 줍니다. 그대로 두면 'PER 낮은순' 정렬에서
적자 기업이 1등이 되므로, 0 은 '계산 불가'로 보고 빈칸으로 저장합니다.
우선주는 보통주(모회사)의 재무지표를 씁니다. DART 는 회사 단위로 공시하므로 삼성전자우(005935)에는 별도 재무제표가 없습니다. 같은 회사인 삼성전자(005930)의 값을 그대로 붙입니다. 한 회사에 종목이 4개까지 달린 경우도 있습니다(현대차·현대차우·2우B·3우B).
분기 ROE 는 연간보다 작게 나옵니다. 분기 보고서는 그 기간만의 이익이라 그렇습니다. 같은 분기끼리(작년 3분기 vs 올해 3분기) 비교하세요.
Neon 무료 플랜은 512MB 한도입니다.
시세 3년치만으로 약 455MB 를 씁니다. 공간을 아끼려고 daily_price 에는
기본키 색인 하나만 둡니다. 한도에 걸리면 오래된 시세를 지우거나
유료 플랜으로 올려야 합니다. 매일 약 0.6MB 씩 늘어납니다.
화면의 영어 메뉴는 한글로 바꿔치기한 것입니다.
가장 먼저:
.venv\Scripts\python.exe -m src.check
| 증상 | 원인과 해결 |
|---|---|
KRX 로그인 실패 | .env 의 KRX_ID/KRX_PW 확인. data.krx.co.kr 에 브라우저로 직접 로그인해 보세요 (비밀번호 변경 요구 화면이 떠 있으면 먼저 변경) |
DATABASE_URL 을 찾지 못했습니다 | .env 가 없거나 값이 비어 있음. copy .env.example .env 후 값 입력 |
| 접속은 되는데 데이터가 0건 | src.backfill 을 아직 안 돌렸거나 도중에 멈춤. 다시 실행하면 이어서 받습니다 |
| Neon 접속이 가끔 느림 | 무료 플랜은 안 쓰면 잠듭니다. 첫 요청 시 몇 초 걸린 뒤 깨어납니다 |