// strategy.js import logger from './logger.js'; import {OpenAI} from "openai"; const prompts = { "1h": `BTC/USDT 1시간 스윙 트레이딩 엔진입니다. - 시간대: 1시간 캔들만. - 일일 거래 빈도 목표: ≥ 3개의 유효 설정. - 거래당 위험: 계좌 잔액의 1% 이하. - 동시에 2개 이상의 포지션을 보유하지 마십시오. - 최종 JSON 외부에 해설을 추가하지 마십시오. [입력] 최근 1시간 캔들 50개(최근 캔들 순, 형식: [{"t":,"o":,"h":,"l":,"c":,"v":}, …] LONG: - 9-EMA > 21-EMA (둘 다 상승). - RSI14가 40~60 사이이고 이전 캔들 대비 상승하는 경우. - Close ≥ VWAP. - Close ≤ 스윙 고점 - ATR14×0.5 (작은 하락 구간). SHORT: - 9-EMA < 21-EMA (둘 다 하락). - RSI14가 40~60 사이이고 이전 캔들 대비 하락하는 경우. - Close ≤ VWAP. - Close ≥ 스윙 저점 + ATR14×0.5 (작은 하락 구간). HOLD: - 매수 또는 매도 조건이 모두 충족되지 않는 경우. JSON만 반환하며, 콜론 뒤에 공백은 포함하지 않습니다. {"side":"LONG|SHORT|HOLD","price":,"sl":,"tp":,"reason":"<최대 200단어>"} 진입 가격(한도) = 현재 캔들 종가 *손절(SL) *익절(TP) 는 제공된 캔들의 추세선으로 설정해주세요.(중요) 모든 가격을 가장 가까운 0.1 USDT로 반올림하세요. reason 은 한국어로 대답해줘.`, '5m': `당신은 2025년 기준 코인 선물 **5분봉 전문 트레이더**입니다. 5분 단위로 신속한 진입/청산이 필수적이며, **2~3배 레버리지**로 고빈도 수익을 추구합니다. 다음 규칙을 철저히 적용하세요. 🔸 롱 포지션 진입 조건 (Long Entry) 다음 모든 조건을 동시에 충족할 경우 매수 진입 시그널 발생: 이동평균선 정배열: 이동평균선 (MA5) > 이동평균선 (MA20) CCI (상대강도지수): CCI > 100 RSI (60~70 구간): RSI > 60 AND RSI < 70 AND 현재 RSI > 이전 RSI (상승 모멘텀 지속 중) (과매수 직전, 강한 상승 모멘텀) 거래량 급증: 현재 캔들 거래량 > 직전 5개 캔들의 평균 거래량 × 1.8 캔들 패턴 보조 필터: 현재 캔들의 종가 > 시가 (양봉, 매수 압력 확인) 🔸 숏 포지션 진입 조건 (Short Entry) 다음 모든 조건을 동시에 충족할 경우 매도 진입 시그널 발생: 이동평균선 역배열: 이동평균선 (MA5) < 이동평균선 (MA20) CCI (과매도 영역): CCI < -100 RSI (하락 신호): RSI < 40 AND RSI > 30 AND 현재 RSI < 이전 RSI (하락 모멘텀 지속 중) 거래량 급증: 현재 캔들 거래량 > 직전 5개 캔들의 평균 거래량 × 1.8 캔들 패턴 보조 필터: 현재 캔들의 종가 < 시가 (음봉, 매도 압력 확인) ⚠️ 공통 리스크 관리 규칙 (SL, TP, 청산) 🛑 스탑로스 (Stop-Loss) 기본 설정 (리스크 1% 이내): 롱 진입 시: SL = 진입가 × 0.99 (1% 하향) 숏 진입 시: SL = 진입가 × 1.01 (1% 상향) 보조 조건 (과도한 슬리피지 방지): 롱 진입 시: SL = MAX(SL, 최근 3개 캔들 중 최저가 × 1.005) 숏 진입 시: SL = MIN(SL, 최근 3개 캔들 중 최고가 × 0.995) ✅ 테이크프로핏 (Take-Profit) 기본 목표 수익률: 롱: TP = 진입가 × 1.02 → +2% 숏: TP = 진입가 × 0.98 → -2% → 리스크 대비 2:1 비율 (SL 1% → TP 2%) **JSON만 반환하며, 콜론 뒤에 공백은 포함하지 않습니다.** {"side":"LONG|SHORT|HOLD","price":,"sl":,"tp":,"reason":"<최대 200단어>"} 아래 5분봉 데이터 입니다. [데이터 타입] [{"t":,"o":,"h":,"l":,"c":,"v":}, …] ` } const openai = new OpenAI({ baseURL: 'https://openrouter.ai/api/v1', apiKey: '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', }); export async function aiSignal(bars) { if (bars.length < 20) return null; console.log(Date.now()) const content = ` ${prompts["5m"]} ${JSON.stringify(bars)} `; const completion = await openai.chat.completions.create({ model: 'qwen/qwen3-coder', messages: [ { role: 'user', content: content, }, ], }); try { console.log(Date.now()) const msg = completion.choices[0].message.content logger.debug(msg); const sig = JSON.parse(msg) return sig; } catch(e) { return {side : 'HOLD'} } }