Skip to content

Latest commit

ย 

History

History
321 lines (242 loc) ยท 16.3 KB

File metadata and controls

321 lines (242 loc) ยท 16.3 KB

BinanceVolatilityBot

BinanceVolatilityBot์€ CCXT๋ฅผ ์ด์šฉํ•˜์—ฌ ์ž๋™๋งค๋งค ๋ด‡์„ ๊ตฌํ˜„ํ•œ ํ”„๋กœ์ ํŠธ์ž…๋‹ˆ๋‹ค. ์ด ๋ด‡์€ ๋ณ€๋™์„ฑ ๋ŒํŒŒ ์ „๋žต๊ณผ EMA ๊ธฐ๋ฐ˜ ์ถ”์„ธ ์ถ”์ข… ์ „๋žต์„ ์ ์šฉํ•˜์—ฌ ์ž๋™์œผ๋กœ ์„ ๋ฌผ๊ฑฐ๋ž˜๋ฅผ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

Manual ยท FAQ ยท Examples ยท Contributing

binancecoinm CCXT Certified CCXT Pro Sign up with Binance COIN-M using CCXT's referral link for a 10% discount!

Thank you CCXT!

์ „๋žต ์†Œ๊ฐœ

๋ณ€๋™์„ฑ ๋ŒํŒŒ ์ „๋žต

๋ณ€๋™์„ฑ ๋ŒํŒŒ ์ „๋žต ์˜ˆ์‹œ ๋ณ€๋™์„ฑ ๋ŒํŒŒ ์ „๋žต ์˜ˆ์‹œ ์‚ฌ์ง„(https://www.tradingview.com/chart/TSLA/vlvAMwqN-Volatility-Breakout-Trading-Explained/)

๋ณ€๋™์„ฑ ๋ŒํŒŒ ์ „๋žต ์›๋ฆฌ

๋ŒํŒŒ ๊ฐ€๊ฒฉ = ํ˜„์žฌ ์‹œ๊ฐ€ + (์ด์ „ ๊ณ ๊ฐ€ - ์ด์ „ ์ €๊ฐ€) * k๊ฐ’

์˜ค๋Š˜ ๊ฐ€๊ฒฉ์ด ๋ŒํŒŒ ๊ฐ€๊ฒฉ์„ ๋„˜์–ด๊ฐ€๋ฉด ๋งค์ˆ˜ํ•˜๊ณ  ๋‹ค์Œ๋‚  ์•„์นจ ์žฅ์ด ์‹œ์ž‘ํ•˜๋ฉด ๋ชจ๋‘ ๋งค๋„ํ•œ๋‹ค.

์ด์ „ ์‹œ๊ฐ€ : $920, ์ด์ „ ๊ณ ๊ฐ€ : $1000, ์ด์ „ ์ €๊ฐ€ : $900, ์ด์ „ ์ข…๊ฐ€ $960

ํ˜„์žฌ ์‹œ๊ฐ€ : $960

๋ŒํŒŒ ๊ฐ€๊ฒฉ = $960 + ($1000 - $900) * 0.6 = $1020

ํ˜„์žฌ ์žฅ์ค‘์— ๋ŒํŒŒ ๊ฐ€๊ฒฉ $1020์„ ๋„˜์–ด์„œ๋ฉด ๋งค์ˆ˜ํ•ด์„œ ๋‹ค์Œ ์‹œ์ž‘์‹œ ๋ชจ๋‘ ๋งค๋„

์˜ค๋Š˜ ๋งค์ˆ˜ํ•ด์„œ ๋‚ด์ผ ํŒ”๊ธฐ ๋•Œ๋ฌธ์— ์‹œ์žฅ ์‹ฌ๋ฆฌ์— ํœ˜๋‘˜๋ฆฌ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์•„๋ž˜๋Š” ์ด๋Ÿฌํ•œ ๋งค๋งค ์ „๋žต์„ ๋ฐฑํ…Œ์ŠคํŒ…์œผ๋กœ ๊ตฌํ˜„ํ•œ ๊ฒฐ๊ณผ์ž…๋‹ˆ๋‹ค. ๋ฐฑํ…Œ์ŠคํŒ… ์ฝ”๋“œ๋Š” backtest.py์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋กฑ ํฌ์ง€์…˜ : ๋ŒํŒŒ์ „๋žต ๋งค์ˆ˜์‹œ ์ˆœ์ด์ต ๋นจ๊ฐ„์ƒ‰์ด ์ˆœ ์ด์ต์ž…๋‹ˆ๋‹ค. ์ˆ˜์ˆ˜๋ฃŒ๋ฅผ ์ œ์™ธํ•˜๊ณ  ๋งค์ˆ˜ ํฌ์ง€์…˜๋งŒ ์žก์„ ์‹œ 200์ผ๊ฐ„์˜ ๋ˆ„์  ์ˆ˜์ต์„ ์ง€ํ‘œ๋กœ ๋‚˜ํƒ€๋‚ด์—ˆ์Šต๋‹ˆ๋‹ค.

MDD : ๋งค์ˆ˜ํฌ์ง€์…˜ MDD MDD(Most Drawdown, ์ตœ๋Œ€ ์†์‹ค ๋‚™ํญ)๋Š” ๋ˆ„์  ์ด์ต๋ฅ ์˜ ์ตœ๋Œ€๊ฐ’(Peak)์—์„œ ๊ฐ€์žฅ ํฌ๊ฒŒ ํ•˜๋ฝํ•œ ๋น„์œจ์„ ๋ฐฑ๋ถ„์œจ๋กœ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

๋งค์ˆ˜ ์ „๋žต - ์ตœ์ข… ๋ˆ„์  ์ˆ˜์ต๋ฅ : 55.5006352412013%, MDD: -9.999630944195218%, ์ตœ์ ์˜ K๊ฐ’: 0.513664700396083

๊ณต๋งค๋„ ๋˜ํ•œ ์›๋ฆฌ๋Š” ๊ฐ™์Šต๋‹ˆ๋‹ค.

์ˆ ํฌ์ง€์…˜ : ๋ŒํŒŒ์ „๋žต ๊ณต๋งค๋„์‹œ ์ˆœ์ด์ต MDD : ๋งค๋„ํฌ์ง€์…˜ MDD MDD(Most Drawdown, ์ตœ๋Œ€ ์†์‹ค ๋‚™ํญ)

๊ณต๋งค๋„ ์ „๋žต - ์ตœ์ข… ๋ˆ„์  ์ˆ˜์ต๋ฅ : 54.35987463558776 %, MDD: -8.271748731020926 %, ์ตœ์ ์˜ K๊ฐ’: 0.8763195978770201

์ง€๋‚œ 200๊ฐ„์€ ์ƒ์Šน์žฅ์ด๋ผ ์ˆ ํฌ์ง€์…˜์˜ ๊ฒฝ์šฐ k๊ฐ’์ด ๋ณด์ˆ˜์ ์œผ๋กœ ์žกํžŒ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์‹ค์ œ๋กœ ์ด๋ ‡๊ฒŒ ์ˆ˜์ต์„ ์–ป์„ ์ˆ˜ ์žˆ์œผ๋ฉด ์ข‹๊ฒ ์ง€๋งŒ ํ˜„์‹ค์€ ๊ทธ๋ ‡์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ํฐ ์„ธ๋ ฅ์ด ๋งค๋ฌผ๋Œ€๋ฅผ ๋šซ๊ณ  ํ•œ ๋ฒˆ์— ๊ณ ๊ฐ€ ๊ฐฑ์‹ ์„ ํ•ด๋ฒ„๋ฆฌ๊ธฐ ๋•Œ๋ฌธ์— ์ ์ ˆํ•œ ๋งค์ˆ˜ ๊ฐ€๊ฒฉ๋Œ€๋ฅผ ๊ตฌํ•˜์ง€ ๋ชปํ•˜๊ณ  ๋†’์€ ๊ฐ€๊ฒฉ์— ์‚ฌ๊ณ  ๋‚ฎ์€ ๊ฐ€๊ฒฉ์— ํŒŒ๋Š” ๋Œ€์ฐธ์‚ฌ๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ฆฌํ•˜์—ฌ Auto ARIMA ๋ชจ๋ธ์„ ์‚ฌ์šฉํ•ด์„œ 15๋ถ„ ๋’ค์˜ ๊ฐ€๊ฒฉ์„ ์˜ˆ์ธกํ•˜๊ณ  ์ ํ•ฉํ•œ ๊ฐ€๊ฒฉ์— ๋งค๋งค๋ฅผ ์ง„ํ–‰ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜์˜€์Šต๋‹ˆ๋‹ค.


EMA ๊ธฐ๋ฐ˜ ์ถ”์„ธ ์ถ”์ข… ์ „๋žต

์ด ์ „๋žต์€ ์ด๋™ ํ‰๊ท ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•œ ์ž๋™๋งค๋งค ์ „๋žต์ž…๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” 9์ผ, 21์ผ, 54์ผ ์ด๋™ ํ‰๊ท ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ฃผ๊ฐ€์˜ ์ถ”์„ธ์™€ ๋ชจ๋ฉ˜ํ…€์„ ํ‰๊ฐ€ํ•˜๊ณ , ๋งค์ˆ˜ ์กฐ๊ฑด์„ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. ์ด ๋งค์ˆ˜ ์ „๋žต์€ ์ž๋™๋งค๋งค ์‹œ์Šคํ…œ์— ์ ์šฉ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ema์ „๋žต

๋งค์ˆ˜ ์กฐ๊ฑด

์ด ์ „๋žต์—์„œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์„ธ ๊ฐ€์ง€ ๋งค์ˆ˜ ์กฐ๊ฑด์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค:

๊ธฐ๋ณธ ๋งค์ˆ˜ ์กฐ๊ฑด (Buy_conditions):
9์ผ ์ด๋™ ํ‰๊ท  (ema_9)์ด 21์ผ ์ด๋™ ํ‰๊ท  (ema_21)๋ณด๋‹ค ํด ๋•Œ.
์กฐ๊ฑด: ema_9 > ema_21
์„ค๋ช…: ์ด ์กฐ๊ฑด์€ ๋‹จ๊ธฐ ์ถ”์„ธ๊ฐ€ ์ค‘๊ธฐ ์ถ”์„ธ๋ณด๋‹ค ๊ฐ•ํ•˜๋‹ค๋Š” ์‹ ํ˜ธ๋กœ ํ•ด์„๋ฉ๋‹ˆ๋‹ค. ์ž๋™๋งค๋งค ์‹œ์Šคํ…œ์€ ์ด ์‹ ํ˜ธ๊ฐ€ ๋ฐœ์ƒํ•  ๋•Œ ํ•ด๋‹น ์ข…๋ชฉ์„ ๋งค์ˆ˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ฐ•ํ•œ ๋งค์ˆ˜ ์กฐ๊ฑด (ema_Buy_conditions):
9์ผ ์ด๋™ ํ‰๊ท ๊ณผ 21์ผ ์ด๋™ ํ‰๊ท ์˜ ์ฐจ์ด (ema_9 - ema_21)๊ฐ€ 21์ผ ์ด๋™ ํ‰๊ท ๊ณผ 54์ผ ์ด๋™ ํ‰๊ท ์˜ ์ฐจ์ด (ema_21 - ema_54)๋ณด๋‹ค ํด ๋•Œ.
์กฐ๊ฑด: (ema_9 - ema_21) > (ema_21 - ema_54)
์„ค๋ช…: ์ด ์กฐ๊ฑด์€ ๋‹จ๊ธฐ ์ƒ์Šน ๋ชจ๋ฉ˜ํ…€์ด ์ค‘๊ธฐ ์ƒ์Šน ๋ชจ๋ฉ˜ํ…€๋ณด๋‹ค ๊ฐ•ํ•˜๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ์ž๋™๋งค๋งค ์‹œ์Šคํ…œ์€ ์ด ์ƒํ™ฉ์„ ๊ฐ•๋ ฅํ•œ ๋งค์ˆ˜ ์‹ ํ˜ธ๋กœ ๊ฐ„์ฃผํ•˜์—ฌ ํ•ด๋‹น ์ข…๋ชฉ์„ ๋” ํ™•์‹  ์žˆ๊ฒŒ ๋งค์ˆ˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด์ „์˜ ๋งค์ˆ˜ ์กฐ๊ฑด ๋ณ€ํ™” (Previous_ema_Buy_conditions):
ํ˜„์žฌ 9์ผ ์ด๋™ ํ‰๊ท ๊ณผ 21์ผ ์ด๋™ ํ‰๊ท ์˜ ์ฐจ์ด (ema_9 - ema_21)๊ฐ€ ์ด์ „ ๊ฐ’๋ณด๋‹ค ํด ๋•Œ.
์กฐ๊ฑด: (ema_9 - ema_21)๊ฐ€ ์ „์ผ์˜ (ema_9 - ema_21)๋ณด๋‹ค ํด ๋•Œ.
์„ค๋ช…: ์ด ์กฐ๊ฑด์€ ๋‹จ๊ธฐ ์ด๋™ ํ‰๊ท ์ด ์ค‘๊ธฐ ์ด๋™ ํ‰๊ท ์— ๋น„ํ•ด ๋” ๋น ๋ฅด๊ฒŒ ์ƒ์Šนํ•˜๊ณ  ์žˆ์Œ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. ์ž๋™๋งค๋งค ์‹œ์Šคํ…œ์€ ์ด ๊ฒฝํ–ฅ์„ ๊ฐ์ง€ํ•˜์—ฌ ๋‹จ๊ธฐ์ ์ธ ๋งค์ˆ˜ ๋ชจ๋ฉ˜ํ…€์„ ํฌ์ฐฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์„œ๋„ Auto ARIMA ๋ชจ๋ธ์„ ์‚ฌ์šฉํ•ด์„œ 5๋ถ„ ๋’ค์˜ ์ตœ์ € ๊ฐ€๊ฒฉ์„ ์˜ˆ์ธกํ•˜๊ณ  ํ•ด๋‹น ๊ฐ€๊ฒฉ๋ณด๋‹ค ๋‚ฎ์„ ๋•Œ ๋งค์ˆ˜๋ฅผ ์ง„ํ–‰ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜์˜€์Šต๋‹ˆ๋‹ค.


์˜ˆ์ธก ๊ธฐ๋Šฅ

ARIMA(Autoregressive Integrated Moving Average)๋ชจ๋ธ์€ ์‹œ๊ณ„์—ด ๋ฐ์ดํ„ฐ๋ฅผ ์˜ˆ์ธกํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋˜๋Š” ๋ชจ๋ธ๋กœ, ์„ธ ๊ฐ€์ง€ ์ฃผ์š” ์š”์†Œ๋กœ ๊ตฌ์„ฑ๋ฉ๋‹ˆ๋‹ค:

์ž๊ธฐํšŒ๊ท€(AR, Autoregressive): ๊ณผ๊ฑฐ ๊ฐ’๋“ค์ด ํ˜„์žฌ ๊ฐ’์— ์˜ํ–ฅ์„ ๋ฏธ์น˜๋Š” ๋ชจ๋ธ์ž…๋‹ˆ๋‹ค.
๋ˆ„์ ์ฐจ๋ถ„(I, Integrated): ๋ฐ์ดํ„ฐ๋ฅผ ์ •์ƒ ์ƒํƒœ๋กœ ๋ณ€ํ™˜ํ•˜๊ธฐ ์œ„ํ•ด ํ•„์š”ํ•œ ์ฐจ๋ถ„ ๊ณผ์ •์ž…๋‹ˆ๋‹ค.
์ด๋™ํ‰๊ท (MA, Moving Average): ๋ฐฑ์ƒ‰ ์žก์Œ์— ์˜ํ•ด ์„ค๋ช…๋˜๋Š” ํ˜„์žฌ ๊ฐ’์˜ ๋ชจ๋ธ์ž…๋‹ˆ๋‹ค.
์ด ์„ธ ๊ฐ€์ง€ ์š”์†Œ๋ฅผ ๊ฒฐํ•ฉํ•˜์—ฌ ARIMA ๋ชจ๋ธ์€ ์‹œ๊ณ„์—ด ๋ฐ์ดํ„ฐ์˜ ํŒจํ„ด์„ ์„ค๋ช…ํ•˜๊ณ  ์˜ˆ์ธกํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

predict_price๋Š” ์ด ARIMA ๋ชจ๋ธ์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ธˆ์œต ์ž์‚ฐ(์˜ˆ: ์ฃผ์‹ ๋˜๋Š” ์•”ํ˜ธํ™”ํ)์˜ ๋ฏธ๋ž˜ ๊ฐ€๊ฒฉ์„ ์˜ˆ์ธกํ•˜๋Š” ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค. ์ด ํ•จ์ˆ˜๋Š” ํŠน์ • ๋ฏธ๋ž˜ ์‹œ๊ฐ„ ๊ฐ„๊ฒฉ์— ๋Œ€ํ•œ ์ข…๊ฐ€๋ฅผ ์˜ˆ์ธกํ•˜๊ณ  ๊ณ ๊ฐ€์™€ ์ €๊ฐ€๋ฅผ ์ถ”์ •ํ•ฉ๋‹ˆ๋‹ค. ํ•จ์ˆ˜์˜ ๊ตฌ์„ฑ ์š”์†Œ์™€ ํ”„๋กœ์„ธ์Šค๋ฅผ ์ž์„ธํžˆ ์„ค๋ช…ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

ํ•จ์ˆ˜ ๋งค๊ฐœ๋ณ€์ˆ˜

prediction_time: ์˜ˆ์ธก ์‹œ๊ฐ„ ๊ฐ„๊ฒฉ์„ ์ง€์ •ํ•˜๋Š” ๋ฌธ์ž์—ด (์˜ˆ: '1h'๋Š” 1์‹œ๊ฐ„, '3m'๋Š” 3๋ถ„ ๋“ฑ).
add_mintes: ์˜ˆ์ธก ๊ฐ„๊ฒฉ์— ์ถ”๊ฐ€ํ•  ์ถ”๊ฐ€ ๋ถ„ ์ˆ˜๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ์ •์ˆ˜ (๊ธฐ๋ณธ๊ฐ’์€ 0).

๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์˜ค๊ธฐ:

ํ•จ์ˆ˜๋Š” get_candles(exchange, symbol, timeframe=prediction_time, limit=200)์„ ํ˜ธ์ถœํ•˜์—ฌ ๊ณผ๊ฑฐ ๊ฐ€๊ฒฉ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค. ์ด ๋ฐ์ดํ„ฐ๋Š” timestamp, open, high, low, close, volume ์—ด์„ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค. ์—ด ์ด๋ฆ„ ๋ณ€๊ฒฝ ๋ฐ ์ธ๋ฑ์‹ฑ:
df = df.rename(columns={'timestamp': 'ds', 'open': 'open', 'high': 'high', 'low': 'low', 'close': 'y', 'volume': 'volume'})
df.set_index('ds', inplace=True)

ARIMA ๋ชจ๋ธ ํ•™์Šต

๋ชจ๋ธ ์ดˆ๊ธฐํ™” ๋ฐ ํ•™์Šต:
auto_arima๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ARIMA ๋ชจ๋ธ์„ ์ดˆ๊ธฐํ™”ํ•˜๊ณ  ํ•™์Šตํ•ฉ๋‹ˆ๋‹ค.
model = auto_arima(df['y'], seasonal=False, suppress_warnings=True)

์˜ˆ์ธก ์‹œ๊ฐ„ ๊ณ„์‚ฐ

prediction_time์— ๋”ฐ๋ผ ์ถ”๊ฐ€ํ•  ๋ถ„(minute)์„ ๊ณ„์‚ฐํ•ฉ๋‹ˆ๋‹ค.

    if prediction_time == '6h':
        minutes_to_add = 60*6
    elif prediction_time == '3m':
        minutes_to_add = 3
    elif prediction_time == '5m':
        minutes_to_add = 5
    elif prediction_time == '15m':
        minutes_to_add = 15
    elif prediction_time == '30m':
        minutes_to_add = 30
    elif prediction_time == '1h':
        minutes_to_add = 60
    elif prediction_time == '1d':
        minutes_to_add = 24 * 60

๋ฏธ๋ž˜ ๋ฐ์ดํ„ฐ ํฌ์ธํŠธ ์ƒ์„ฑ

๋ฏธ๋ž˜ ์‹œ์ ์— ๋Œ€ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

future = pd.DataFrame(index=[df.index[-1] + pd.Timedelta(minutes=minutes_to_add)])
future['open'] = df['open'].iloc[-1]
future['high'] = df['high'].iloc[-1]
future['low'] = df['low'].iloc[-1]
future['volume'] = df['volume'].iloc[-1]

์˜ˆ์ธก ์ˆ˜ํ–‰

๋ชจ๋ธ์„ ์‚ฌ์šฉํ•˜์—ฌ ์˜ˆ์ธก์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.
forecast, conf_int = model.predict(n_periods=1, exogenous=[future.values], return_conf_int=True)

์˜ˆ์ธก ๊ฒฐ๊ณผ ์ €์žฅ

์˜ˆ์ธก๋œ ์ข…๊ฐ€๋ฅผ ์ €์žฅํ•˜๊ณ  ๊ณ ๊ฐ€์™€ ์ €๊ฐ€๋ฅผ ์˜ˆ์ธก ๊ตฌ๊ฐ„(confidence interval)์œผ๋กœ๋ถ€ํ„ฐ ๊ณ„์‚ฐํ•ฉ๋‹ˆ๋‹ค.

close_value = forecast[0]
predicted_close_price = close_value
predicted_high_price = conf_int[0][1]
predicted_low_price = conf_int[0][0]

๊ฒฐ๋ก 

์ด ํ•จ์ˆ˜๋Š” ์ฃผ์–ด์ง„ ์‹œ๊ฐ„ ๊ฐ„๊ฒฉ ํ›„์˜ ์ข…๊ฐ€๋ฅผ ์˜ˆ์ธกํ•˜๊ณ , ์‹ ๋ขฐ ๊ตฌ๊ฐ„์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ณ ๊ฐ€์™€ ์ €๊ฐ€๋ฅผ ์ถ”์ •ํ•˜๋Š” ๊ณผ์ •์„ ์ž๋™ํ™”ํ•ฉ๋‹ˆ๋‹ค.

๋ฆฌ์Šคํฌ ๊ด€๋ฆฌ

์ •ํ•ด์ง„ ์‹œ๊ฐ„์— ํฌ์ง€์…˜ ์ข…๋ฃŒ

UTC ๊ธฐ์ค€ 00:00, 06:00, 12:00, 18:00์— ๋ด‡์ด ์žก์€ ๋ชจ๋“  ํฌ์ง€์…˜์€ ์ข…๋ฃŒ๋ฉ๋‹ˆ๋‹ค.
datetime.datetime.now() >= entry_time + datetime.timedelta(hours=(6 - entry_time.hour % 6))

์—ญ์ถ”์„ธ ๋ŒํŒŒ

์—ญ์ถ”์„ธ ๋ŒํŒŒ์‹œ K๊ฐ’์€ ๊ธฐ์กด๊ฐ’์˜ 0.3์„ ๋”ํ•œ ์ˆ˜์น˜์ž…๋‹ˆ๋‹ค.(0.55 + 0.3)
์˜ˆ์ธก ๋˜ํ•œ predict_price(prediction_time='15m')๋กœ ๋ณ€๋™์„ฑ์ด ์‹ฌํ•˜๋‹ค๊ณ  ํŒ๋‹จ๋˜์–ด ๋ณด์ˆ˜์ ์œผ๋กœ ์ง€์ •ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

๊ณผ๋งค์ˆ˜ ๋ฐ ๊ณผ๋งค๋„ ์‹ ํ˜ธ

์Šคํ† ์บ์Šคํ‹ฑ RSI : RSI๊ฐ€ 70์„ ๋„˜์–ด์„œ๋ฉด ๊ณผ๋งค์ˆ˜ ์ƒํƒœ๋กœ ๊ฐ„์ฃผ๋  ์ˆ˜ ์žˆ๊ณ , 30 ๋ฐ‘์œผ๋กœ ๋–จ์–ด์ง€๋ฉด ๊ณผ๋งค๋„ ์ƒํƒœ๋กœ ๊ฐ„์ฃผ๋ฉ๋‹ˆ๋‹ค.
์Šคํ† ์บ์Šคํ‹ฑ RSI์˜ ์ดํƒˆ ์ง€์ ์„ ํ†ตํ•ด ์ƒˆ๋กœ์šด ํฌ์ง€์…˜์— ์ง„์ž…์„ ์ œํ•œ ํ•˜๋Š” ๋ฐ์— ํ™œ์šฉํ•˜์˜€์Šต๋‹ˆ๋‹ค.

def stochastic_rsi(data, period=14, smooth_k=3, smooth_d=3):
    """
    ์Šคํ† ์ผ€์Šคํ‹ฑ RSI๋ฅผ ๊ณ„์‚ฐํ•˜๋Š” ํ•จ์ˆ˜.

    ๋งค๊ฐœ๋ณ€์ˆ˜:
    - data: 'high', 'low', 'close' ์—ด์„ ํฌํ•จํ•œ DataFrame.
    - period: RSI ๊ธฐ๊ฐ„ (๊ธฐ๋ณธ๊ฐ’์€ 14).
    - smooth_k: %K๋ฅผ ๋ถ€๋“œ๋Ÿฝ๊ฒŒ ๋งŒ๋“ค๊ธฐ ์œ„ํ•œ ๊ธฐ๊ฐ„ (๊ธฐ๋ณธ๊ฐ’์€ 3).
    - smooth_d: %D๋ฅผ ๋ถ€๋“œ๋Ÿฝ๊ฒŒ ๋งŒ๋“ค๊ธฐ ์œ„ํ•œ ๊ธฐ๊ฐ„ (๊ธฐ๋ณธ๊ฐ’์€ 3).
    ๋ฐ˜ํ™˜๊ฐ’:
    - 'stoch_rsi_k' ๋ฐ 'stoch_rsi_d'.
    """
    # RSI ๊ณ„์‚ฐ
    data = calculate_rsi(data, period)

    # ์Šคํ† ์ผ€์Šคํ‹ฑ RSI (%K) ๊ณ„์‚ฐ
    min_rsi = data['rsi'].rolling(window=period, center = False).min()
    max_rsi = data['rsi'].rolling(window=period, center = False).max()
    stoch = 100 * (data['rsi'] - min_rsi) / (max_rsi - min_rsi)
    stoch_rsi_k = stoch.rolling(window=smooth_k, center = False).mean()
    # ์Šคํ† ์ผ€์Šคํ‹ฑ RSI (%D) ๊ณ„์‚ฐ
    stoch_rsi_d = stoch_rsi_k.rolling(window=smooth_d, center = False).mean()
    return stoch_rsi_k, stoch_rsi_d

๊ณผ๋งค์ˆ˜ ์ดํƒˆ ์ง€์  : (stoch_rsi_k.iloc[-2]<100 and stoch_rsi_d.iloc[-2] < 95) or (stoch_rsi_k.iloc[-3] == 100 and stoch_rsi_d.iloc[-3] == 100)
๊ณผ๋งค๋„ ์ดํƒˆ ์ง€์  : (stoch_rsi_k.iloc[-2] > 0 and stoch_rsi_d.iloc[-2] > 5) or (stoch_rsi_k.iloc[-3] == 0 and stoch_rsi_d.iloc[-3] == 0)

์•Œ์ˆ˜์—†๋Š” ์ด์œ ๋กœ ์ •์ƒ๊ฐ’์€ 2๊ฐœ ์ด์ „๊ฐ’์œผ๋กœ ๋‚˜์˜ค๋‹ˆ ์ด์— ๋Œ€ํ•ด ์•Œ๊ณ  ์žˆ๋‹ค๋ฉด ๋ฉ”์ผ์ด๋‚˜ ์ด์Šˆ๋กœ ์•Œ๋ ค์ฃผ์„ธ์š”.

Profit_Percentage์ผ์ • ์ด์ƒ ์†์ต์‹œ ํฌ์ง€์…˜ ์ข…๋ฃŒ

์†์ ˆ๊ฐ€

long_stop_loss = (df['low'].iloc[-1] + df['open'].iloc[-2])/2
short_stop_loss = (df['high'].iloc[-1] + df['open'].iloc[-2])/2
๋งŒ์•ฝ ์†์ ˆ๊ฐ€๋ณด๋‹ค ์˜ˆ์ธก๊ฐ€๊ฒฉ์ด ๋” ๋ฒ—์–ด๋‚˜์žˆ๋‹ค๋ฉด predict_price(prediction_time='3m')์œผ๋กœ ํฌ์ง€์…˜ ์ง€์ ์„ ์žฌ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.

์ˆ˜์ˆ˜๋ฃŒ ์ ˆ์•ฝ์„ ์œ„ํ•œ ์ง€์ •๊ฐ€ ์ฃผ๋ฌธ์‹œ ์ฑ„๊ฒฐ์ด ๋˜์ง€ ์•Š์„ ๊ฒฝ์šฐ UTC ๊ธฐ์ค€ 00:00, 06:00, 12:00, 18:00์— ์ทจ์†Œ๋ฉ๋‹ˆ๋‹ค.

์ž๋™๋งค๋งค ์‹œ์ž‘ํ•˜๊ธฐ

ํŒจํ‚ค์ง€ ์„ค์น˜

์ด ํ”„๋กœ์ ํŠธ๋ฅผ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋จผ์ € ํŒจํ‚ค์ง€๋ฅผ ์„ค์น˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์•„๋ž˜ ๋ช…๋ น์–ด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์„ค์น˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

git clone https://github.com/ddjunho/BinanceVolatilityBot.git
cd BinanceVolatilityBot
pip install .

๋˜๋Š” ๊ฐœ๋ฐœ ํ™˜๊ฒฝ์—์„œ ํŒจํ‚ค์ง€๋ฅผ ์„ค์น˜ํ•  ๊ฒฝ์šฐ:

pip install -e .

Binance API ํ‚ค ์„ค์ •

binance_keys.py ํŒŒ์ผ์„ ์ž‘์„ฑํ•˜์—ฌ Binance API ํ‚ค์™€ ์‹œํฌ๋ฆฟ ํ‚ค๋ฅผ ์„ค์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

# binance_keys.py

api_key = 'your_binance_api_key'
api_secret = 'your_binance_api_secret'
cd BinanceVolatilityBot
echo -e "api_key = 'your_binance_api_key'\napi_secret = 'your_binance_api_secret'" > binance_keys.py

Telegram ์„ค์ •

BotFather๋ฅผ ํ†ตํ•ด ๋ด‡์„ ์ƒ์„ฑ ํ›„ telepot_bot_id.py ํŒŒ์ผ์„ ์ž‘์„ฑํ•˜์—ฌ Telegram ๋ด‡์˜ API ํ† ํฐ๊ณผ ์ฑ„ํŒ… ID๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

# telepot_bot_id.py

token = 'your_telegram_bot_token'
chat_id = 'your_telegram_chat_id'
cd BinanceVolatilityBot
echo -e "token = 'your_telegram_bot_token'\nchat_id = 'your_telegram_chat_id'" > telepot_bot_id.py

Telegram ์‚ฌ์šฉ๋ฒ•

์ด Telegram ๋ด‡์€ ์•”ํ˜ธํ™”ํ ์ž๋™๋งค๋งค ์‹œ์Šคํ…œ์„ ์œ„ํ•ด ์„ค๊ณ„๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž๊ฐ€ Telegram์„ ํ†ตํ•ด ๋ช…๋ น์–ด๋ฅผ ์ž…๋ ฅํ•˜๋ฉด, ํ•ด๋‹น ๋ด‡์€ ์‚ฌ์šฉ์ž๊ฐ€ ์„ค์ •ํ•œ ์กฐ๊ฑด์— ๋”ฐ๋ผ ์ž๋™์œผ๋กœ ์•”ํ˜ธํ™”ํ๋ฅผ ๋งค๋งคํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ๊ฐ ๋ช…๋ น์–ด๋ฅผ ์ •ํ™•ํžˆ ์ž…๋ ฅํ•˜์—ฌ ์›ํ•˜๋Š” ์„ค์ •์„ ๋ณ€๊ฒฝํ•˜๊ฑฐ๋‚˜ ์ •๋ณด๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ธฐ๋Šฅ ๋ชฉ๋ก

์‹œ์ž‘ ๋ฐ ์ค‘์ง€
/start: ์ž๋™๋งค๋งค๋ฅผ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค.
/stop: ์ž๋™๋งค๋งค๋ฅผ ์ค‘์ง€ํ›„ ์ดˆ๊ธฐํ™”ํ•ฉ๋‹ˆ๋‹ค.

๋„์›€๋ง
/help: ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋ชจ๋“  ๋ช…๋ น์–ด์™€ ๊ฐ ๋ช…๋ น์–ด์˜ ์„ค๋ช…์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

๋ ˆ๋ฒ„๋ฆฌ์ง€ ์„ค์ •
/leverage(num): ๋ ˆ๋ฒ„๋ฆฌ์ง€ ๊ฐ’์„ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. (num์€ 1์—์„œ 10 ์‚ฌ์ด์˜ ๊ฐ’)
์˜ˆ์‹œ: /leverage(5)

K ๊ฐ’ ์„ค์ •
/set(k): K ๊ฐ’์„ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. (k๋Š” 0.2์—์„œ 0.75๊นŒ์ง€ 0.05 ๋‹จ์œ„๋กœ ์„ค์ • ๊ฐ€๋Šฅ)
์˜ˆ์‹œ: /set(0.5)

์ต์ ˆ ์ˆ˜์น˜ ์„ค์ •
/Profit_Percentage(num): ์ต์ ˆ ์ˆ˜์น˜๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. (num์€ 100์—์„œ 200 ์‚ฌ์ด์˜ ๊ฐ’)
์˜ˆ์‹œ: /Profit_Percentage(120)

๊ฐ€๊ฒฉ ์˜ˆ์ธก
/predict_3m, /predict_5m, /predict_15m, /predict_1h, /predict_6h, /predict_1d: ๊ฐ๊ฐ 3๋ถ„, 5๋ถ„, 15๋ถ„, 1์‹œ๊ฐ„, 6์‹œ๊ฐ„, 1์ผ ๋’ค์˜ ๊ฐ€๊ฒฉ์„ ์˜ˆ์ธกํ•ฉ๋‹ˆ๋‹ค.

์กฐ๊ฑด ์ถฉ์กฑ ์ฝ”์ธ ๋ชฉ๋ก
/Condition_fulfillment_symbols: ema ์กฐ๊ฑด์„ ์ถฉ์กฑํ•˜๋Š” ์•”ํ˜ธํ™”ํ ์‹ฌ๋ณผ ๋ชฉ๋ก์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

์‹คํ–‰

๋ฐฑ๊ทธ๋ผ์šด๋“œ๋กœ BinanceVolatilityBot์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์•„๋ž˜์˜ ๋ช…๋ น์–ด๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

cd BinanceVolatilityBot
nohup python3 BinanceVolatilityBot.py > output.log &

ํ…Œ์ŠคํŠธ

๋ŒํŒŒ์˜ ๊ธฐ์ค€์ธ k๊ฐ’์„ ๊ตฌํ•˜๋ ค๋ฉด backtest.py ์„ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. ๋งค์ˆ˜์™€ ๋งค๋„์˜ ์ตœ์ข… ๋ˆ„์  ์ˆ˜์ต๋ฅ ์„ ๊ตฌํ•˜๊ณ  ์ตœ์ ์˜ k๊ฐ’์„ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’ : 0.55

python3 tests/backtest.py

๊ฐ„๋‹จํ•œ ์ ๊ฒ€๋ฅผ ์ˆ˜ํ–‰ํ•˜๋ ค๋ฉด test_binance_volatility_bot.py ํŒŒ์ผ์„ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

pytest tests/test_binance_volatility_bot.py

ํ…Œ์ŠคํŠธ๋Š” ์ •์ƒ์ ์œผ๋กœ ์ž‘๋™ํ•˜๋Š”์ง€ ํ™•์ธํ•˜๊ณ , ํ•„์š”ํ•œ ๊ฒฝ์šฐ ์ถ”๊ฐ€์ ์ธ ์œ ๋‹› ํ…Œ์ŠคํŠธ๋ฅผ ์ž‘์„ฑํ•˜์—ฌ ๊ธฐ๋Šฅ์„ ๊ฒ€์ฆํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ฃผ์˜์‚ฌํ•ญ

ํ˜„์žฌ๋Š” ์ด๋”๋ฆฌ์›€(ETHUSDT)๋งŒ ๊ฑฐ๋ž˜ํ•˜๋„๋ก ์„ค์ •๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

์„ ๋ฌผ ์‹œ์žฅ์—์„œ ๊ฑฐ๋ž˜๋ฅผ ์ˆ˜ํ–‰ํ•˜๋ฉฐ, ๋งค์ˆ˜์™€ ๊ณต๋งค๋„ ์–‘ ๋ฐฉํ–ฅ ํฌ์ง€์…˜์œผ๋กœ ์ „๋žต์ด ๊ตฌํ˜„๋˜์–ด์žˆ์Šต๋‹ˆ๋‹ค.

๋ ˆ๋ฒ„๋ฆฌ์ง€๋Š” ์ด์ต์„ ๊ทน๋Œ€ํ™”ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ๋™์‹œ์— ์†์‹ค๋„ ๋ฐฐ์ˆ˜๋กœ ์ปค์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋ ˆ๋ฒ„๋ฆฌ์ง€ ์‚ฌ์šฉ ์‹œ ์‹ ์ค‘์„ ๊ธฐํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ˆ˜์ˆ˜๋ฃŒ๋Š” ๊ณ ๋ คํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.

API ํ‚ค์™€ ์‹œํฌ๋ฆฟ ํ‚ค, Telegram ๋ด‡์˜ ํ† ํฐ๊ณผ ์ฑ„ํŒ… ID๋Š” ์™ธ๋ถ€์— ๋…ธ์ถœ๋˜์ง€ ์•Š๋„๋ก ์ฃผ์˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์‹ค์ „ ๊ฑฐ๋ž˜์— ์•ž์„œ ์ถฉ๋ถ„ํ•œ ๋ฐฑํ…Œ์ŠคํŒ…๊ณผ ์‹œ๋ฎฌ๋ ˆ์ด์…˜์„ ์ง„ํ–‰ํ•˜์—ฌ ์ „๋žต์˜ ์‹ ๋ขฐ์„ฑ์„ ๊ฒ€์ฆํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.