자동 거래 시스템으로, 다양한 금융 데이터를 수집하고 분석하여 거래 신호를 제공합니다.
- 주식 및 암호화폐 데이터 수집
- 기술적 분석 지표 계산
- 다중 시간대 분석 (일봉 + 분봉)
- 일봉 200개: 장기적 추세 분석
- 60분 캔들 12개: 중기적 방향성 (하루 전반적 상승/하락 추세)
- 5분 캔들 12개: 단기적 모멘텀과 변동성
- 1분 캔들 10개: 초단기 급등락 및 거래량 폭증 포착
- 자동 거래 신호 생성
- Telegram 봇을 통한 알림
- 웹 대시보드
- Python 3.13+
- UV (패키지 관리)
- PostgreSQL
- Redis
- 저장소 클론
git clone <repository-url>
cd auto_trader- 의존성 설치
uv sync --all-groups- 환경 변수 설정
cp env.example .env
# .env 파일을 편집하여 필요한 설정값 입력필수 환경 변수:
UPBIT_ACCESS_KEY: 업비트 API 액세스 키UPBIT_SECRET_KEY: 업비트 API 시크릿 키KIS_APP_KEY: 한국투자증권 API 앱 키KIS_APP_SECRET: 한국투자증권 API 시크릿GOOGLE_API_KEY: Google Gemini API 키TELEGRAM_TOKEN: Telegram 봇 토큰DATABASE_URL: PostgreSQL 데이터베이스 연결 URLREDIS_URL: Redis 연결 URL
- 데이터베이스 마이그레이션
uv run alembic upgrade head- 애플리케이션 실행
uv run uvicorn app.main:api --reload- Freqtrade research pipeline runbook:
docs/runbooks/freqtrade-research-pipeline.md - Summary ingestion command:
uv run python scripts/ingest_freqtrade_report.py --input /absolute/path/to/summary.json --runner macsearch_symbol(query, limit=20)get_quote(symbol, market=None)get_holdings(account=None, market=None, include_current_price=True, minimum_value=None)get_position(symbol, market=None)get_ohlcv(symbol, count=100, period="day", end_date=None, market=None)get_volume_profile(symbol, market=None, period=60, bins=20)screen_stocks(...)- Screen stocks across different markets (KR/US/Crypto) with various filters.
Parameters:
market: Market to screen ("kr", "us", "crypto") (default: "kr")asset_type: Asset type ("stock", "etf", "etn") - only applicable to KRcategory: Category filter (ETF categories for KR, sector for US)sector: Sector filter for KR/US stocks (default: None). Not supported for crypto or KR ETF/ETN requestssort_by: Sort criteria ("volume", "trade_amount", "market_cap", "change_rate", "dividend_yield") (default: crypto="trade_amount", KR/US="volume")sort_order: Sort order ("asc" or "desc") (default: "desc")min_market_cap: Minimum market cap filter (억원 for KR, USD for US; not supported for crypto, warning returned)max_per: Maximum P/E ratio filter (not applicable to crypto)min_dividend_yield: Minimum dividend yield filter (accepts both decimal, e.g., 0.03, and percentage, e.g., 3.0; values > 1 are treated as percentages) (not applicable to crypto)min_dividend: Alias formin_dividend_yield. Accepts same format. If both specified, they must be equalmin_analyst_buy: Minimum analyst buy count filter (default: None). Only supported for KR/US stocks (not ETF/ETN)max_rsi: Maximum RSI filter (0-100, filters out overbought)limit: Maximum number of results to return (1-50, capped at 50)sort_by: Sort criteria ("volume", "trade_amount", "market_cap", "change_rate", "dividend_yield") (default: crypto="trade_amount", KR/US="volume")sort_order: Sort order ("asc" or "desc") (default: "desc")min_market_cap: Minimum market cap filter (억원 for KR, USD for US; not supported for crypto, warning returned)max_per: Maximum P/E ratio filter (not applicable to crypto)min_dividend_yield: Minimum dividend yield filter (accepts both decimal, e.g., 0.03, and percentage, e.g., 3.0; values > 1 are treated as percentages) (not applicable to crypto)max_rsi: Maximum RSI filter (0-100, filters out overbought)limit: Maximum number of results to return (1-50, capped at 50)
Response format:
{
"results": [...],
"total_count": N, // Total stocks that passed all filters (before sort/limit). If data source provides total, uses that; otherwise uses fetched candidates count.
"returned_count": M, // Actual number of results returned (after limit)
"filters_applied": {...},
"market": "kr|us|crypto",
"timestamp": "ISO timestamp"
}MCP 서버는 시장/보유종목 조회 및 주문 처리 도구를 제공합니다.
- 조회 도구: 실시간 시세, 차트(OHLCV), 보조지표, 보유종목/잔고 조회
- 주문 도구: 주문 이력 조회(
get_order_history), 신규 주문(place_order), 정정/취소(modify_order,cancel_order)
Market-specific behavior:
-
KR market: Uses KRX API for stocks/ETFs + Naver Finance for valuation metrics.
- KRX data cached with 300s TTL (Redis) + in-memory fallback
- Trading date auto-fallback (up to 10 days back)
- Category filter auto-limits to ETFs if
asset_type=None - ETN (
asset_type="etn") not supported - returns error
-
US market: Uses tvscreener first for stock requests, then falls back to yfinance when TradingView fields are unavailable or the request needs an unsupported sort.
- US
category/sectorfilters stay on the tvscreener path when TradingView sector metadata is available - Public enrichment fields (
sector,analyst_buy,analyst_hold,analyst_sell,avg_target,upside_pct) are filled directly from tvscreener when possible; missing values use lightweight Finnhub/yfinance fallback - Legacy yfinance filters:
min_market_cap→intradaymarketcap,max_per→peratio_lasttwelvemonths,min_dividend_yield→forward_dividend_yield - Legacy yfinance sort maps:
volume→dayvolume,market_cap→intradaymarketcap,change_rate→percentchange
- US
-
Crypto market: Uses Upbit top traded coins.
- Default sort is
trade_amountand maps toacc_trade_price_24h(24h traded value in KRW) sort_by="volume"is not supported for crypto and returns an error (usetrade_amount)- Crypto response payload uses
trade_amount_24hand does not includevolume max_per,min_dividend_yield,sort_by="dividend_yield"not supported - returns errorsectorandmin_analyst_buyfilters are not supported for crypto - returns error- RSI calculated using OHLCV data (subset due to API limits: min(len(candidates), limit*3, 150))
- Default sort is
Filter compatibility and error semantics:
sectorfilter: Supported for KR/US stocks only. Returns error for crypto or KR ETF/ETN requestsmin_analyst_buyfilter: Supported for KR/US stocks only (not ETF/ETN). Returns error for crypto or non-stock asset typesmin_dividend/min_dividend_yield: These are aliases. Accepts decimal (0.03) or percentage (3.0) formats. If both are specified with different values, returns error. Not supported for crypto- RSI calculated using OHLCV data (subset due to API limits: min(len(candidates), limit*3, 150))
Advanced filters (PER/dividend/RSI) apply to subset:
- Note:
min_market_capis NOT an advanced filter - it uses data already available from KRX/yfinance, so it doesn't trigger external API calls - Advanced filters (PER, dividend yield, RSI) require external data fetch for KR market
- Limit:
min(len(candidates), limit*3, 150) - Parallel fetch with
asyncio.Semaphore(10) - Timeout: 30 seconds
- Individual failures don't stop overall operation
- 저장소 클론
git clone <repository-url>
cd auto_trader자세한 내용은 app/mcp_server/README.md를 참고하세요.
업비트 API를 사용하여 암호화폐를 분석합니다. 일봉 200개와 함께 다음 분봉 데이터를 자동으로 수집합니다:
- 60분 캔들 (최근 12개): 중기적 방향성 분석
- 5분 캔들 (최근 12개): 단기적 모멘텀 분석
- 1분 캔들 (최근 10개): 초단기 변동성 분석
from app.analysis.service_analyzers import UpbitAnalyzer
analyzer = UpbitAnalyzer()
await analyzer.analyze_coins(["KRW-BTC", "KRW-ETH"])Yahoo Finance API를 사용하여 미국 주식을 분석합니다:
from app.analysis.service_analyzers import YahooAnalyzer
analyzer = YahooAnalyzer()
await analyzer.analyze_stocks(["AAPL", "GOOGL", "MSFT"])한국투자증권 API를 사용하여 국내 주식을 분석합니다:
from app.analysis.service_analyzers import KISAnalyzer
analyzer = KISAnalyzer()
await analyzer.analyze_stock("삼성전자")참고: KIS 분봉 데이터는 API 제한으로 인해 일부 상황에서 작동하지 않을 수 있습니다. 이 경우 일봉 데이터만으로 분석을 수행하며, 분봉 데이터 수집 실패 시에도 분석은 정상적으로 진행됩니다.
KIS 분봉 API 제한사항: 현재 KIS 분봉 API의 time_unit 파라미터가 제대로 작동하지 않아 모든 시간대에서 동일한 데이터가 반환됩니다. 이는 API 자체의 문제로, 향후 한국투자증권의 API 문서 업데이트나 기술지원을 통해 해결될 예정입니다.
개발 의존성 설치:
uv sync --all-groups- Fast gate (
live제외):make test또는uv run pytest tests/ -v -m "not live" - 단위 테스트만:
make test-unit또는uv run pytest tests/ -v -m "not integration and not live" - 통합 테스트만 (
live제외):make test-integration또는uv run pytest tests/ -v -m "integration and not live" - 옛
tests/test_services.py범위 검증:make test-services-split - Live API 테스트:
make test-live또는uv run pytest tests/ -v -m "integration and live" --run-live --no-cov - 커버리지 리포트:
make test-cov또는uv run pytest tests/ -v -m "not live" --cov=app --cov-report=html --cov-report=term-missing - CI fast gate 재현:
CI=true uv run pytest tests/ -m "not live" -n auto --dist=loadfile -ra --durations=25 --durations-min=1.0 -o faulthandler_timeout=120 --cov=app --cov-report=xml --cov-fail-under=30
live 테스트는 integration의 strict subset입니다. 기본 로컬 fast gate는 항상 직렬 -m "not live"를 사용하고, GitHub Actions fast gate만 -n auto --dist=loadfile로 병렬 실행합니다. @pytest.mark.live 테스트는 --run-live를 명시적으로 전달해야 실행됩니다.
@pytest.mark.unit: 단위 테스트@pytest.mark.integration: 통합 테스트@pytest.mark.live: 외부 API 호출 테스트 (integration의 strict subset,--run-live필요)@pytest.mark.slow: 느린 테스트 (선택적 실행)
코드 포맷팅:
make format린팅 검사:
make lint보안 검사:
make securitymake help # 사용 가능한 명령어 목록
make install # 프로덕션 의존성 설치
make install-dev # 개발 의존성 설치
make test # live 제외 fast gate 테스트 실행
make test-services-split # 옛 test_services.py 범위 검증
make test-live # live 통합 테스트 실행 (--run-live)
make test-cov # 커버리지와 함께 테스트 실행
make lint # 코드 품질 검사
make format # 코드 포맷팅
make clean # 생성된 파일 정리
make dev # 개발 서버 시작tests/
├── __init__.py
├── conftest.py # 공통 fixture 및 설정
├── test_settings.py # 테스트 환경 설정
├── test_config.py # 설정 모듈 테스트
├── test_routers.py # API 라우터 테스트
├── test_analysis.py # 분석 모듈 테스트
├── test_services_*.py # 서비스 모듈 테스트 (도메인별 분리)
└── test_integration.py # 통합 테스트
tests/test_services_*.py는 삭제된 tests/test_services.py의 정확한 별칭이 아닙니다. 이 패턴은 tests/test_services_krx.py도 포함하므로, 예전 단일 파일 범위와 동일한 검증이 필요하면 make test-services-split를 사용하세요.
GitHub Actions를 통해 자동으로 다음을 실행합니다:
- 린팅: Ruff 린터 + 포맷터, ty 타입 체커
- 테스트: Python 3.13에서 fast gate를 병렬 실행하고 후속 TaskIQ smoke tests를 수행 (lint 통과 후)
- 보안: bandit, safety 검사
- 커버리지: 테스트 커버리지 리포트 생성
OTEL/Grafana 전용 스택은 제거되었습니다. 현재 표준 모니터링은 Sentry입니다.
SENTRY_DSN=
SENTRY_ENVIRONMENT=
SENTRY_TRACES_SAMPLE_RATE=1.0
SENTRY_PROFILES_SAMPLE_RATE=1.0
SENTRY_SEND_DEFAULT_PII=true
SENTRY_ENABLE_LOG_EVENTS=trueSENTRY_DSN이 있으면 환경과 무관하게 활성화- release는 Docker 스크립트/예제로 주입한 컨테이너 빌드 SHA를 우선 사용하고, 비컨테이너 로컬 실행은 현재 git HEAD에서 자동 해상도
- 단일 프로젝트에서
service태그로 프로세스 분리 logger.error이벤트 수집 활성화- 민감 필드(
authorization,cookie,token,secret,password)는 마스킹
이 프로젝트는 MIT 라이센스 하에 배포됩니다.