레슨 29: 머신러닝 및 전략 최적화
발행: (2025년 12월 3일 오후 12:03 GMT+9)
4 min read
원문: Dev.to
Source: Dev.to
⏱ Duration: 2.5 시간
🎯 학습 목표
- 머신러닝을 활용하여 전략 개발 및 파라미터 최적화를 지원하는 방법을 학습합니다
강좌 개요
머신러닝(ML)은 다음과 같이 도와줄 수 있습니다:
- 🔍 데이터에서 숨겨진 패턴 발견
- 🎯 전략 파라미터 최적화
- 📊 가격 추세 예측
- 🤖 적응형 전략 구축
Important Reminders
- ⚠️ 머신러닝은 ‘만능 해결책’이 아니며 수익을 보장하지 못합니다.
- ⚠️ 대량의 데이터와 계산 자원이 필요합니다.
- ⚠️ 과적합이 발생하기 쉬우며, 신중히 검증해야 합니다.
- ⚠️ 이 강의는 이론적 깊이보다는 실용적인 방법에 초점을 맞춥니다.
Part 1: Freqtrade의 Hyperopt
1.1 Hyperopt 소개
Hyperopt는 머신러닝 알고리즘을 사용해 최적 파라미터를 자동으로 찾는 Freqtrade의 내장 파라미터 최적화 도구입니다.
기본 개념
What is Hyperopt?
- Automated parameter search
- Uses Bayesian optimization algorithms
- Searches for optimal parameters within specified ranges
- Scores based on backtest results
What can be optimized?
- Buy condition parameters (RSI thresholds, EMA periods)
- Sell condition parameters
- ROI configuration
- Stop loss configuration
- Trailing stop loss configuration
최적화 공간
Freqtrade supports 5 optimization spaces:
1. buy – Buy condition parameters
2. sell – Sell condition parameters
3. roi – ROI configuration
4. stoploss – Stop loss configuration
5. trailing – Trailing stop loss configuration
Can optimize individually or in combination.
1.2 Hyperopt 호환 전략 준비
전략 파일을 생성합니다. 예: user_data/strategies/HyperoptableStrategy.py:
from freqtrade.strategy import IStrategy, IntParameter, DecimalParameter, CategoricalParameter
from pandas import DataFrame
import talib.abstract as ta
import freqtrade.vendor.qtpylib.indicators as qtpylib
from functools import reduce
class HyperoptableStrategy(IStrategy):
"""
Hyperopt‑compatible strategy
Define optimizable parameter ranges
"""
INTERFACE_VERSION = 3
# ===== Optimizable Parameters =====
# Buy parameters
buy_rsi_threshold = IntParameter(20, 40, default=30, space='buy')
buy_rsi_enabled = CategoricalParameter([True, False], default=True, space='buy')
buy_ema_short = IntParameter(5, 20, default=9, space='buy')
buy_ema_long = IntParameter(15, 50, default=21, space='buy')
# Sell parameters
sell_rsi_threshold = IntParameter(60, 80, default=70, space='sell')
sell_rsi_enabled = CategoricalParameter([True, False], default=True, space='sell')
# ROI parameters (static example)
minimal_roi = {
"0": 0.10,
"30": 0.05,
"60": 0.03,
"120": 0.01
}
# Stop loss parameter
stoploss = -0.10
# Trailing stop loss parameters
trailing_stop = True
trailing_stop_positive = 0.01
trailing_stop_positive_offset = 0.02
trailing_only_offset_is_reached = True
timeframe = '5m'
startup_candle_count: int = 50
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
# EMA (using optimizable periods)
for val in self.buy_ema_short.range:
dataframe[f'ema_short_{val}'] = ta.EMA(dataframe, timeperiod=val)
for val in self.buy_ema_long.range:
dataframe[f'ema_long_{val}'] = ta.EMA(dataframe, timeperiod=val)
# RSI
dataframe['rsi'] = ta.RSI(dataframe, timeperiod=14)
# Volume mean
dataframe['volume_mean'] = dataframe['volume'].rolling(window=20).mean()
return dataframe
def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
conditions = []
# EMA golden cross
conditions.append(
qtpylib.crossed_above(
dataframe[f'ema_short_{self.buy_ema_short.value}'],
dataframe[f'ema_long_{self.buy_ema_long.value}']
)
)
# RSI (if enabled)
if self.buy_rsi_enabled.value:
conditions.append(dataframe['rsi'] > self.buy_rsi_threshold.value)
conditions.append(dataframe['rsi'] dataframe['volume_mean'])
conditions.append(dataframe['volume'] > 0)
if conditions:
dataframe.loc[reduce(lambda x, y: x & y, conditions), 'enter_long'] = 1
return dataframe
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
conditions = []
# EMA death cross
conditions.append(
qtpylib.crossed_below(
dataframe[f'ema_short_{self.buy_ema_short.value}'],
dataframe[f'ema_long_{self.buy_ema_long.value}']
)
)
# RSI (if enabled)
if self.sell_rsi_enabled.value:
conditions.append(dataframe['rsi'] > self.sell_rsi_threshold.value)
# Volume filter
conditions.append(dataframe['volume'] > 0)
if conditions:
dataframe.loc[reduce(lambda x, y: x & y, conditions), 'exit_long'] = 1
return dataframe
핵심 포인트
# Integer parameter
buy_rsi_threshold = IntParameter(20, 40, default=30, space='buy')
# Search within 20‑40 range, default 30
# Decimal parameter
stoploss = DecimalParameter(-0.15, -0.05, default=-0.10, space='stoploss')
# Search within -0.15 to -0.05 range
# Categorical parameter (True/False)
buy_rsi_enabled = CategoricalParameter([True, False], default=True, space='buy')
1.3 Hyperopt 실행
기본 명령
# Optimize buy parameters only
freqtrade hyperopt \
-c config.json \
--strategy HyperoptableStrategy \
--hyperopt-loss SharpeHyperOptLoss \
--spaces buy \
--epochs 100
--hyperopt-loss– 최적화 목표