Open Net Worth
Open Net Worth is an open-source personal AI wealth assistant you run yourself: one ledger for your whole financial life, worked by an AI agent you control.
翻訳待ち
코인 자동매매 매크로 생성 플랫폼
翻訳待ち
Loading the full README. The saved excerpt is shown below.
코인 매크로 백테스트 & 공유 서비스 (MVP) 실거래 없이, 내가 만든 코인 매매 규칙(매크로)을 과거 시세로 시뮬레이션(백테스트) 하고, 결과를 인증 카드로 공유하며, 남의 매크로를 복제해서 다시 돌려보는 서비스입니다. ⚠️ 이 서비스는 실제 주문/자동매매를 하지 않습니다. 거래소 주문 API 연동이 전혀 없습니다. 모든 수익률은 과거 데이터 시뮬레이션 결과이며 화면·카드에 항상 배지로 명시됩니다. 스택 • 백엔드: Python 3.11+ / FastAPI, pandas, numpy, SQLModel(SQLite) • 시세: Binance 공개 klines REST (인증 불필요) + 로컬 SQLite 캐시 • 공유 카드: 서버 Pillow 렌더링 (GET /api/card/{slug}.png) • 프론트: React + Vite + TailwindCSS (SPA) 1) 백엔드 (필수 — 엔진/API/카드/테스트 전부 여기서 동작) • API 문서: http://localhost:8000/docs • 헬스체크: http://localhost:8000/api/healthRead the full README ↗
실거래 없이, 내가 만든 코인 매매 규칙(매크로)을 과거 시세로 시뮬레이션(백테스트) 하고, 결과를 인증 카드로 공유하며, 남의 매크로를 복제해서 다시 돌려보는 서비스입니다.
⚠️ 이 서비스는 실제 주문/자동매매를 하지 않습니다. 거래소 주문 API 연동이 전혀 없습니다. 모든 수익률은 과거 데이터 시뮬레이션 결과이며 화면·카드에 항상 배지로 명시됩니다.
klines REST (인증 불필요) + 로컬 SQLite 캐시GET /api/card/{slug}.png)cd backend
python -m pip install -r requirements.txt
python -m pytest # 엔진 + API 유닛테스트 (18개) 통과 확인
python -m uvicorn app.main:app --reload --port 8000
⚠️ Node.js 18+ 가 필요합니다 (이 저장소가 만들어진 환경엔 Node가 없어 프론트는 빌드/실행 검증을 못 했습니다. 백엔드는 전부 검증됨). Node 설치 후:
cd frontend
npm install
npm run dev # http://localhost:5173 (/api 는 8000 으로 프록시)
프로덕션 단일 프로세스로 돌리려면:
cd frontend && npm run build # frontend/dist 생성
cd ../backend && python -m uvicorn app.main:app --port 8000
# 이제 http://localhost:8000 에서 SPA + API 가 한 포트로 동작 (딥링크 fallback 포함)
backend/engine/매매 판단 코드는 저장소에 한 벌만 둔다. 백테스트 · 서버 실시간 · 실행기가 맞춰야 할 계약이 전부 여기서 나온다. 두 벌이 되면 백테스트 결과와 실거래가 조용히 갈라진다.
실행기는 Tauri(Rust) 앱이다 — orbleeparrot/ggparrot-desktop, 매매 루프는
src-tauri/crates/runner-core. 파이썬 패키지를 그대로 import 할 수 없으므로, "같은 코드"
대신 같은 답을 계약으로 박는다(backend/tests/fixtures/engine_golden.json).
(gg_parrot/runner/ 의 파이썬 · Tk 실행기는 옛 경로이고 배포되지 않는다.)
engine 은 app 을 거꾸로 참조하지 않는다. 서버 전용 코드(DB · 캔들 수급 · API)는
app/ 에 남는다 — 봉 피드가 app/candle_feed.py 에 있는 것도 그래서다. 그래야 판단을
읽는 데 DB 도 웹 프레임워크도 필요 없고, 계약을 서버 없이 만들 수 있다.schema · exchanges · intervals · leverage · stepper ·
candles · driver · live_session · live_levels · entry_filter · bundle ·
version)의 바깥 의존성은 pydantic 하나다.backtest · walkforward · portfolio* · explain · summary ·
validation)은 pandas · numpy 를 쓴다. engine/__init__.py 가 이 이름들을 지연 import 해
판단 경로와 섞이지 않게 한다.경계는 backend/tests/test_engine_package_boundary.py 가 지킨다.
tests/fixtures/engine_golden.json엔진이 두 언어로 존재하므로 "같은 코드" 라고 말할 수 없다. 대신 같은 입력에 같은 답을 글로 박아 두고 양쪽을 잰다. 고정된 90개 봉에 여섯 규칙(D · E · F · G · H · I)을 돌려 나온 주문 명령 · 거래 수 · 끝 자산이 그 계약이다.
backend/tests/test_engine_golden.py 가 지금 엔진이 그 답을 그대로 내는지 본다.판단을 의도적으로 바꿨다면 --regolden 으로 다시 만들고 ENGINE_VERSION 도 올린다.
안 올리면 옛 실행기가 조용히 다른 답을 낸다. 두 값이 어긋나면 시험이 깨진다.
봉은 여섯 규칙이 전부 실제로 사고팔도록 일부러 섞어 만들었다 — 아무것도 안 사는 계약은 아무것도 보장하지 않는다. 그 사실 자체를 보초 시험이 지킨다.
engine/version.py실행기가 스스로 판단하게 되면 엔진이 사용자 PC 마다 다른 세대로 돈다. 웹에서 본 백테스트는 서버의 최신 엔진이 낸 결과인데 손에 든 실행기가 옛 엔진이면 같은 매크로가 다른 자리에서 사고판다. 늦게 사는 것은 보이지만 다르게 사는 것은 안 보인다.
실행기는 세션을 시작할 때 자기 ENGINE_VERSION 을 함께 보내고, 서버는 매크로가 요구하는
세대보다 낮으면 426 으로 돌려보낸다. 세대를 밝히지 않는 실행기는 통과시킨다 — 지금
배포된 실행기 전부가 그렇고, 판단을 서버가 하므로 그 엔진 세대는 결과에 영향이 없다.
판정이 달라지는 변경(진입·청산 계산, 새 규칙·파라미터, 체결·수수료)을 넣을 때:
ENGINE_VERSION 을 1 올린다._MIN_ENGINE_BY_RULE 에 적는다.문구·로그·성능·서버 전용 코드 변경으로는 올리지 않는다. 적지 않으면 게이트는 통과시키고, 옛 실행기가 조용히 다른 답을 낸다.
RUNNER_LOCAL_DECISIONS원칙: 우리 서버 장애가 사용자의 매수 · 매도 시점을 좌우하면 안 된다. 못 판 것만 귀책이 아니라 못 산 것도 귀책이다. 그래서 봉 받기와 매매 판단은 실행기 안에서 끝난다.
| 서버 판단(지금 기본) | 실행기 판단 | |
|---|---|---|
| 봉 받기 | 서버가 거래소에서 | 실행기가 거래소에서 직접 |
| 진입 · 청산 판단 | 서버 드라이버 | 실행기(Rust, 구현 예정) |
| 손절 · 일일 손실 · 보유시간 | 실행기 | 실행기 (그대로) |
| 주문 | 실행기 | 실행기 (그대로, 같은 길) |
| 전략 상태 · 체결 기록 | 서버가 씀 | 실행기가 올리고 서버는 비추기만 |
| 원격 종료 · 청산 | 서버 → 실행기 | 서버 → 실행기 (그대로) |
켜는 법: 서버에 RUNNER_LOCAL_DECISIONS=true. 기본은 꺼짐 — 거래 흐름을 바꾸는
전환이라 코드가 다 들어간 뒤에도 운영에서 한 번 더 켠다. 실행기는 늘 "내가 판단하겠다"
(decides: "local")고 말하고, 켤지는 서버가 정해 시작 응답(decides)으로 알려 준다 —
양쪽이 동시에 판단하면 같은 신호로 두 번 산다.
실행기 쪽은 아직 없다 — Tauri(Rust) 앱(orbleeparrot/ggparrot-desktop)에 봉 수집과
판단을 구현해야 켤 수 있다. 서버 쪽은 받을 준비가 끝났다: 로컬 세션에는 드라이버를 띄우지
않고 명령도 주지 않으며, local_fills · strategy_state 를 받아 적고 비춘다.
켠 뒤 알아 둘 것:
last_heartbeat_at 으로 언제 본
값인지 함께 읽어야 한다.local_fills)이 리더보드 · 수익률 ·
활동 기록의 전부다. 서버가 명령을 내던 때는 '냈던 명령' 이라도 알았지만 이제는 모른다.서버와 실행기가 같은 결론을 내는지는 위 판단 계약(engine_golden.json)으로 잰다.
commission_pct (기본 0.1%).slippage_pct (기본 0.05%). 매수는 높게, 매도는 낮게 체결.funding_pct (기본 0, 경로만 구현 — 파라미터로 조정 가능).leverage=1이면 현물과 동일하고 청산이 없습니다(기존과 완전히 동일). 2배 이상이면 격리 마진 청산 시뮬레이션이 켜집니다(아래 별도 섹션). 숏 수익률은 부호 반전(가격 하락=이익).amount_per_buy가 투입액을 정하므로 invest_ratio 미적용.매수횟수 × amount_per_buy) 대비 최종 평가금액. 매수-후-보유라 승률은 최종 손익 부호로 표기(참고용).⚠️ 백테스트·페이퍼(가짜 돈)에만 적용됩니다. 실거래(bot.py)에는 레버리지를 적용하지 않습니다. 정밀 바이낸스식(마크 프라이스·구간별 유지증거금·펀딩)과 다른 단순 근사식입니다. 목적은 "화려한 수익률"이 아니라 레버리지가 얼마나 위험한지 가짜 돈으로 안전하게 체험하게 하는 것입니다.
This is the beginning of the README. Read the rest at the original. Read the full README ↗