Timeframe
15m
Direction
Long & Short
Stoploss
-2.0%
Trailing Stop
No
ROI
0m: 4.0%, 60m: 2.0%, 120m: 1.0%, 240m: 0.0%
Interface Version
N/A
Startup Candles
1000
Indicators
7
freqtrade/freqtrade-strategies
Strategy 003 author@: Gerald Lonlas github@: https://github.com/freqtrade/freqtrade-strategies
import pandas as pd
import numpy as np
import talib.abstract as ta
from freqtrade.strategy import IStrategy
from typing import Optional
class Aquma1(IStrategy):
# 기본 설정
timeframe = '15m'
process_only_new_candles = True
startup_candle_count = 1000
can_short = True
use_exit_signal = True
stoploss = -0.02
minimal_roi = {
"0": 0.04,
"60": 0.02,
"120": 0.01,
"240": 0
}
def __init__(self, config: dict, **kwargs):
super().__init__(config, **kwargs)
from xgboost import XGBClassifier
import joblib
self.model = None
try:
self.model = joblib.load('/freqtrade/user_data/models/aquma1_xgb.pkl')
except Exception as e:
print(f"모델 로드 실패: {e}")
def populate_indicators(self, dataframe: pd.DataFrame, metadata: dict) -> pd.DataFrame:
# 기술적 지표 계산 (talib 사용)
dataframe['RSI'] = ta.RSI(dataframe, timeperiod=14)
dataframe['MFI'] = ta.MFI(dataframe, timeperiod=14)
dataframe['ADX'] = ta.ADX(dataframe, timeperiod=14)
dataframe['EMA_20'] = ta.EMA(dataframe['close'], timeperiod=20)
# MACD 계산
macd, macdsignal, macdhist = ta.MACD(
dataframe['close'], fastperiod=12, slowperiod=26, signalperiod=9
)
dataframe['MACD'] = macd
dataframe['MACD_signal'] = macdsignal
dataframe['MACD_hist'] = macdhist
# Bollinger Bands 계산 (nbdevup/nbdevdn는 float로 전달)
bb_upper, bb_middle, bb_lower = ta.BBANDS(
dataframe['close'], timeperiod=20, nbdevup=2.0, nbdevdn=2.0, matype=0
)
dataframe['BB_upper'] = bb_upper
dataframe['BB_middle'] = bb_middle
dataframe['BB_lower'] = bb_lower
# Stochastic Oscillator 계산
stoch_k, stoch_d = ta.STOCH(
dataframe['high'], dataframe['low'], dataframe['close'],
fastk_period=14, slowk_period=3, slowd_period=3
)
dataframe['Stoch_%K'] = stoch_k
dataframe['Stoch_%D'] = stoch_d
# Directional Indicators 계산
dataframe['DI_plus'] = ta.PLUS_DI(
dataframe['high'], dataframe['low'], dataframe['close'], timeperiod=14
)
dataframe['DI_minus'] = ta.MINUS_DI(
dataframe['high'], dataframe['low'], dataframe['close'], timeperiod=14
)
# 결측치 제거 대신 채우기를 사용하여 데이터프레임 길이 유지
dataframe.fillna(0, inplace=True)
# 모델 입력 피처 준비 (훈련시 사용한 순서와 동일하게)
feature_columns = [
'RSI', 'MFI', 'ADX', 'EMA_20', 'MACD', 'MACD_signal', 'MACD_hist',
'BB_upper', 'BB_middle', 'BB_lower', 'Stoch_%K', 'Stoch_%D', 'DI_plus', 'DI_minus'
]
features = dataframe[feature_columns].values
# 머신러닝 모델 예측 (상승 확률)
if self.model:
try:
proba = self.model.predict_proba(features)
dataframe['pred_prob'] = proba[:, 1]
except Exception as e:
dataframe['pred_prob'] = 0.0
else:
dataframe['pred_prob'] = 0.0
return dataframe
def populate_entry_trend(self, dataframe: pd.DataFrame, metadata: dict) -> pd.DataFrame:
dataframe['enter_long'] = 0
dataframe['enter_short'] = 0
# 조건 완화 (예측 확률, RSI, EMA 및 ADX 조건)
long_conditions = [
dataframe['pred_prob'] > 0.55,
dataframe['RSI'] < 40,
dataframe['close'] > dataframe['EMA_20'],
dataframe['ADX'] > 20
]
if long_conditions:
dataframe.loc[np.logical_and.reduce(long_conditions), 'enter_long'] = 1
short_conditions = [
dataframe['pred_prob'] < 0.45,
dataframe['RSI'] > 60,
dataframe['close'] < dataframe['EMA_20'],
dataframe['ADX'] > 20
]
if short_conditions:
dataframe.loc[np.logical_and.reduce(short_conditions), 'enter_short'] = 1
return dataframe
def populate_exit_trend(self, dataframe: pd.DataFrame, metadata: dict) -> pd.DataFrame:
dataframe['exit_long'] = 0
dataframe['exit_short'] = 0
# 청산 조건 설정: 롱 포지션은 예측 확률이 낮거나 RSI가 높으면, 숏 포지션은 반대로 설정
exit_long_cond = (dataframe['pred_prob'] < 0.5) | (dataframe['RSI'] > 60)
exit_short_cond = (dataframe['pred_prob'] > 0.5) | (dataframe['RSI'] < 40)
dataframe.loc[exit_long_cond, 'exit_long'] = 1
dataframe.loc[exit_short_cond, 'exit_short'] = 1
return dataframe