반응형
안녕하세요! 지금까지 만든 내용을 그대로 실행 가능한 코드 묶음으로 정리해 깃허브에 올릴 수 있도록, 폴더 구조 + 핵심 파일 + 최소 실행 코드를 한 번에 드립니다. 이대로 복사해 레포를 만들면 바로 테스트넷에서 돌아가요.

레포지토리 구조
- README.md
- LICENSE (MIT 예시)
- .gitignore
- .env.example
- requirements.txt
- Dockerfile
- src/
- config.py
- binance_client.py
- data.py
- strategy.py
- risk.py
- trade.py
- monitor.py
- bot.py ← 24시간 운영 루프
- backtest.py ← 과거 데이터 검증
- paper.py ← 실시간 가상(페이퍼) 트레이딩
GitHub - dataob/autocoin
Contribute to dataob/autocoin development by creating an account on GitHub.
github.com
1) README.md
# Binance Futures GPT Autotrade (Python)
이 프로젝트는 Binance Futures(선물)에서 **SMA 교차 신호**를 기반으로
**리스크 관리(손절/익절, 포지션 사이징)** 를 적용해 자동주문을 수행합니다.
처음에는 **Testnet**에서 충분히 검증한 뒤 실전에 적용하세요.
## 주요 기능
- 선물 캔들 데이터 수집 (python-binance)
- SMA(단기/장기) 교차 신호 생성
- 리스크 관리(손절·익절·포지션 크기 자동 산출)
- 시장가 주문 실행 + 예외 처리
- 디스코드 웹훅 알림
- 백테스트 및 페이퍼 트레이딩
- Docker 컨테이너 실행 지원
## 빠른 시작
1. 레포 클론
2. `cp .env.example .env` 후 환경변수 채우기 (키는 절대 커밋 금지)
3. `pip install -r requirements.txt`
4. 테스트넷 권장: `.env`의 `BINANCE_TESTNET=true`
5. 백테스트: `python src/backtest.py`
6. 페이퍼: `python src/paper.py`
7. 실거래 봇(테스트넷): `python src/bot.py`
## 주의
- API 키에 **출금 권한을 절대 부여하지 마세요**.
- **테스트넷**에서 최소 1~2주 운용 후 실전에 전환하세요.
- 본 프로젝트는 교육용 샘플입니다. 손익은 전적으로 본인 책임입니다.
2) LICENSE
MIT License
Copyright (c) 2025 …
Permission is hereby granted, free of charge, …
3) .gitignore
# Python
__pycache__/
*.pyc
.venv/
venv/
# Env/Secrets
.env
# OS/IDE
.DS_Store
.idea/
.vscode/
4) .env.example
# Binance API
BINANCE_API_KEY=YOUR_KEY
BINANCE_API_SECRET=YOUR_SECRET
BINANCE_TESTNET=true
# Trading
SYMBOL=BTCUSDT
INTERVAL=1h
SHORT_WINDOW=10
LONG_WINDOW=30
LEVERAGE=3
RISK_PERCENT=1.0
STOP_PERCENT=0.5
TAKE_PERCENT=1.0
ORDER_MIN_QTY=0.001
# Discord
DISCORD_WEBHOOK_URL=
# Misc
LOG_LEVEL=INFO
5) requirements.txt
python-binance
pandas
python-dotenv
ta
requests
6) Dockerfile
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt
COPY src ./src
COPY .env ./.env
CMD ["python", "src/bot.py"]
7) src/config.py
import os
from dotenv import load_dotenv
load_dotenv()
SYMBOL = os.getenv("SYMBOL", "BTCUSDT")
INTERVAL = os.getenv("INTERVAL", "1h")
SHORT_WINDOW = int(os.getenv("SHORT_WINDOW", 10))
LONG_WINDOW = int(os.getenv("LONG_WINDOW", 30))
LEVERAGE = int(os.getenv("LEVERAGE", 3))
RISK_PERCENT = float(os.getenv("RISK_PERCENT", 1.0))
STOP_PERCENT = float(os.getenv("STOP_PERCENT", 0.5))
TAKE_PERCENT = float(os.getenv("TAKE_PERCENT", 1.0))
ORDER_MIN_QTY = float(os.getenv("ORDER_MIN_QTY", 0.001))
BINANCE_API_KEY = os.getenv("BINANCE_API_KEY", "")
BINANCE_API_SECRET = os.getenv("BINANCE_API_SECRET", "")
BINANCE_TESTNET = os.getenv("BINANCE_TESTNET", "true").lower() == "true"
DISCORD_WEBHOOK_URL = os.getenv("DISCORD_WEBHOOK_URL", "")
LOG_LEVEL = os.getenv("LOG_LEVEL", "INFO")
8) src/binance_client.py
from binance.client import Client
from binance.exceptions import BinanceAPIException
from .config import BINANCE_API_KEY, BINANCE_API_SECRET, BINANCE_TESTNET
def get_client() -> Client:
client = Client(BINANCE_API_KEY, BINANCE_API_SECRET, testnet=BINANCE_TESTNET)
return client
def ensure_futures_settings(client, symbol, leverage=3, isolated=True):
try:
if isolated:
client.futures_change_margin_type(symbol=symbol, marginType='ISOLATED')
except BinanceAPIException:
pass
try:
client.futures_change_leverage(symbol=symbol, leverage=leverage)
except BinanceAPIException:
pass
9) src/data.py
import pandas as pd
from .config import SYMBOL, INTERVAL
from .binance_client import get_client
client = get_client()
def get_klines(symbol=SYMBOL, interval=INTERVAL, limit=100):
kl = client.futures_klines(symbol=symbol, interval=interval, limit=limit)
df = pd.DataFrame(kl, columns=[
'timestamp','open','high','low','close','volume',
'close_time','quote_asset_volume','trades',
'taker_base','taker_quote','ignore'
])
df['timestamp'] = pd.to_datetime(df['timestamp'], unit='ms')
df[['open','high','low','close','volume']] = df[['open','high','low','close','volume']].astype(float)
return df
10) src/strategy.py
import ta
def apply_sma_signal(df, short_window=10, long_window=30):
df['SMA_Short'] = ta.trend.sma_indicator(df['close'], window=short_window)
df['SMA_Long'] = ta.trend.sma_indicator(df['close'], window=long_window)
prev_short, prev_long = df['SMA_Short'].iloc[-2], df['SMA_Long'].iloc[-2]
curr_short, curr_long = df['SMA_Short'].iloc[-1], df['SMA_Long'].iloc[-1]
if prev_short < prev_long and curr_short > curr_long:
return "BUY"
if prev_short > prev_long and curr_short < curr_long:
return "SELL"
return "HOLD"
11) src/risk.py
from .binance_client import get_client
client = get_client()
def get_balance(asset='USDT'):
bal = client.futures_account_balance()
for it in bal:
if it['asset'] == asset:
return float(it['balance'])
return 0.0
def set_stop_take(entry_price, stop_percent=0.5, take_percent=1.0, side='BUY'):
if side == 'BUY':
sl = entry_price * (1 - stop_percent/100)
tp = entry_price * (1 + take_percent/100)
else:
sl = entry_price * (1 + stop_percent/100)
tp = entry_price * (1 - take_percent/100)
return round(sl, 2), round(tp, 2)
def position_size(balance, risk_percent, entry_price, stop_price, leverage=3):
risk_amt = balance * (risk_percent/100.0)
per_unit = abs(entry_price - stop_price)
if per_unit == 0:
return 0.0
qty = (risk_amt / per_unit) * leverage
return round(qty, 4)
12) src/monitor.py
import requests
from .config import DISCORD_WEBHOOK_URL
def notify(msg: str):
if not DISCORD_WEBHOOK_URL:
return
try:
requests.post(DISCORD_WEBHOOK_URL, json={"content": msg}, timeout=5)
except Exception:
pass
13) src/trade.py
from binance.enums import SIDE_BUY, SIDE_SELL, ORDER_TYPE_MARKET
from binance.exceptions import BinanceAPIException
from .binance_client import get_client
from .monitor import notify
client = get_client()
def last_price(symbol: str) -> float:
ticker = client.futures_symbol_ticker(symbol=symbol)
return float(ticker['price'])
def market_order(symbol: str, side: str, quantity: float):
if quantity <= 0:
notify("❗수량이 0 이하입니다. 주문 취소")
return None
try:
order = client.futures_create_order(
symbol=symbol,
side=SIDE_BUY if side == "BUY" else SIDE_SELL,
type=ORDER_TYPE_MARKET,
quantity=quantity
)
return order
except BinanceAPIException as e:
notify(f"🚨 주문 실패: {e.message}")
return None
14) src/bot.py ← 운영 루프(테스트넷 권장)
import time
from datetime import datetime
from .config import (SYMBOL, INTERVAL, SHORT_WINDOW, LONG_WINDOW,
LEVERAGE, RISK_PERCENT, STOP_PERCENT, TAKE_PERCENT, ORDER_MIN_QTY)
from .binance_client import get_client, ensure_futures_settings
from .data import get_klines
from .strategy import apply_sma_signal
from .risk import get_balance, set_stop_take, position_size
from .trade import last_price, market_order
from .monitor import notify
client = get_client()
ensure_futures_settings(client, SYMBOL, leverage=LEVERAGE, isolated=True)
def run():
while True:
try:
df = get_klines(SYMBOL, INTERVAL, 100)
signal = apply_sma_signal(df, SHORT_WINDOW, LONG_WINDOW)
price = last_price(SYMBOL)
bal = get_balance()
if signal in ("BUY", "SELL"):
sl, tp = set_stop_take(price, STOP_PERCENT, TAKE_PERCENT, signal)
qty = position_size(bal, RISK_PERCENT, price, sl, LEVERAGE)
qty = max(qty, ORDER_MIN_QTY)
order = market_order(SYMBOL, signal, qty)
if order:
notify(f"✅ {signal} {qty} @ {price} | SL {sl} / TP {tp} | bal {bal:.2f}")
else:
notify(f"⚠️ 주문 미체결: {signal} {qty}")
else:
print(f"[{datetime.now()}] HOLD | price {price}")
time.sleep(3600) # 1시간 주기 (INTERVAL=1h일 때 권장)
except Exception as e:
notify(f"⚠️ 루프 오류: {e}")
time.sleep(60)
if __name__ == "__main__":
run()
15) src/backtest.py
from .data import get_klines
from .strategy import apply_sma_signal
def backtest(symbol='BTCUSDT', interval='1h', limit=1000, fee=0.0004):
df = get_klines(symbol, interval, limit)
balance = 1000.0
position = None
entry = 0.0
wins, losses = 0, 0
for i in range(2, len(df)):
sig = apply_sma_signal(df.iloc[:i+1], 10, 30)
price = df['close'].iloc[i]
if sig == 'BUY' and position != 'LONG':
if position == 'SHORT':
pnl = (entry - price) / entry - fee
balance *= (1 + pnl)
wins += int(pnl > 0); losses += int(pnl <= 0)
position, entry = 'LONG', price
elif sig == 'SELL' and position != 'SHORT':
if position == 'LONG':
pnl = (price - entry) / entry - fee
balance *= (1 + pnl)
wins += int(pnl > 0); losses += int(pnl <= 0)
position, entry = 'SHORT', price
print(f"최종 잔액: {balance:.2f} USDT")
print(f"수익률: {(balance-1000)/10:.2f}%")
print(f"승/패: {wins}/{losses}")
if __name__ == "__main__":
backtest()
16) src/paper.py
import time
from datetime import datetime
from .data import get_klines
from .strategy import apply_sma_signal
from .trade import last_price
def paper(symbol='BTCUSDT', interval='1h'):
print("📈 페이퍼 트레이딩 시작")
while True:
df = get_klines(symbol, interval, 100)
sig = apply_sma_signal(df, 10, 30)
price = last_price(symbol)
print(f"[{datetime.now()}] 신호: {sig} | 가격: {price}")
time.sleep(3600)
if __name__ == "__main__":
paper()
맺음말
여기까지 복사해 깃허브에 올리면 바로 실행 가능한 최소 구현 레포가 됩니다.
처음엔 반드시 테스트넷 + 소액 수량으로 검증하시고,
운영 전엔 디스코드 알림과 로그가 정상 동작하는지 꼭 점검해주세요.
필요하시면 다음 포스팅에서 Streamlit 대시보드・Docker Compose・전략 멀티화까지 이어서 확장해드릴게요.
GitHub - dataob/autocoin
Contribute to dataob/autocoin development by creating an account on GitHub.
github.com
반응형
'Python' 카테고리의 다른 글
| 파이썬 & VScode 설치 방법 기초 가이드 (0) | 2025.10.05 |
|---|---|
| VScode에서 파이썬 가상환경 설정 방법 기초 가이드 (0) | 2025.10.05 |
| 바이낸스 선물 GPT 자동매매 7편 : 운영 자동화 & 실시간 모니터링 시스템 구축 (0) | 2025.10.05 |
| 바이낸스 선물 GPT 자동매매 6편 : 백테스트 & 페이퍼 트레이딩 시스템 구축 (0) | 2025.10.05 |
| 바이낸스 선물 GPT 자동매매 5편 : 리스크 관리 & 포지션 사이징 (0) | 2025.10.05 |