Files
bot/strategy.js
2025-08-31 05:42:31 +09:00

64 lines
2.5 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// strategy.js
import logger from './logger.js';
import {OpenAI} from "openai";
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;
// const time = '15분'
const time = '1시간'
console.log(Date.now())
const completion = await openai.chat.completions.create({
model: 'qwen/qwen3-235b-a22b-2507',
messages: [
{
role: 'user',
content: `
You are a BTC/USDT 1-hour swing-trading engine.
- Timeframe: 1h candles only.
- Daily trade frequency target: ≥ 3 valid setups.
- Risk per trade: 1 % of account or less.
- Reward-to-Risk: minimum 2.0, target 2.5.
- Never hold more than 1 concurrent position.
- Do not add commentary outside the final JSON.
[INPUT]
Exactly 50 recent 1-hour candles, newest last, format:
[{"t":<Unix ts>,"o":<float>,"h":<float>,"l":<float>,"c":<float>,"v":<float>}, …]
LONG :
- 9-EMA > 21-EMA (both rising)
- RSI14 between 40 and 65 and increasing vs previous candle
- Close ≥ VWAP
- Close ≤ Swing High - ATR14×0.5 (small pullback zone)
SHORT : exact opposite of LONG.
HOLD : if neither LONG nor SHORT conditions are met.
Return JSON only, no spaces after colons:
{"side":"LONG|SHORT|HOLD","price":<float>,"sl":<float>,"tp":<float>,"reason":"<max 200 words>"}
Entry Price (limit) = current candle close ± 0.05 % toward desired direction.
Stop-Loss (SL) = Entry ± ATR14 × 1.0 (beyond nearest Swing Low/High).
Take-Profit (TP) = Entry ± ATR14 × 2.5 (minimum 2 R).
Round all prices to exchange tick size (0.1 USDT).
reason 은 한국어로 대답해줘.
${JSON.stringify(bars)}
`,
},
],
});
console.log(Date.now())
const msg = completion.choices[0].message.content
logger.info(msg);
const sig = JSON.parse(msg)
return sig;
}