pomoschnik-po-torgam-na-fore/bot.js

227 lines
8.4 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.

const { Bot } = require("grammy");
// Токен из .env (не хардкодить!)
const bot = new Bot(process.env.BOT_TOKEN || "7891234567:AAF_z8kN3xQ5vR9mP2wL7tY4uH6jK1sD0cB");
// === БАЗА ДАННЫХ ПОЛЬЗОВАТЕЛЕЙ ===
let users = new Set();
// === СИГНАЛЫ И НОВОСТИ ===
const signals = [
{ pair: 'EUR/USD', dir: '📈', type: 'Покупка', entry: 1.0850, sl: 1.0830, tp: 1.0890, time: '10:45' },
{ pair: 'GBP/USD', dir: '📉', type: 'Продажа', entry: 1.2680, sl: 1.2710, tp: 1.2620, time: '10:30' },
{ pair: 'XAU/USD', dir: '📈', type: 'Покупка', entry: 2035, sl: 2025, tp: 2055, time: '09:50' },
{ pair: 'BTC/USD', dir: '📉', type: 'Продажа', entry: 42500, sl: 43200, tp: 41100, time: '09:20' }
];
const news = [
{ title: '🔴 Решение по ставке ФРС (США)', time: '14:00', impact: 'Важно' },
{ title: '🔴 Инфляция CPI (Еврозона)', time: '12:00', impact: 'Важно' },
{ title: '🟡 ВВП Великобритании', time: '09:30', impact: 'Средне' },
{ title: '🟢 Розничные продажи (Япония)', time: '08:30', impact: 'Слабо' }
];
const candles = [
{ name: '🔨 Молот (Hammer)', type: 'Бычий разворот', desc: 'Появляется после нисходящего тренда. Длинная нижняя тень.' },
{ name: '☄️ Падающая звезда', type: 'Медвежий разворот', desc: 'Длинная верхняя тень, отскок от сопротивления.' },
{ name: '📈 Бычье поглощение', type: 'Бычий разворот', desc: 'Зелёная свеча перекрывает предыдущую красную.' },
{ name: '📉 Медвежье поглощение', type: 'Медвежий разворот', desc: 'Красная свеча перекрывает предыдущую зелёную.' },
{ name: '➕ Доджи (Doji)', type: 'Неопределённость', desc: 'Цена открытия = цена закрытия.' },
{ name: '🌅 Утренняя звезда', type: 'Бычий разворот', desc: '3 свечи: красная, маленькая, зелёная.' },
{ name: '🌆 Вечерняя звезда', type: 'Медвежий разворот', desc: '3 свечи: зелёная, маленькая, красная.' }
];
// === КОМАНДЫ ===
bot.command("start", async (ctx) => {
users.add(ctx.from.id);
await ctx.reply(
`👋 Привет, ${ctx.from.first_name}!
📊 *Forex Assistant Bot* — твой помощник в торговле
💰 Стартовый капитал: $100
📈 Графики, сигналы, новости, свечи
*Команды:*
/signals — текущие сигналы
/news — важные новости
/candles — справочник свечей
/risk — калькулятор риска
/help — помощь
⚠️ Это обучающий бот. Реальные деньги — только через брокера.`,
{ parse_mode: "Markdown" }
);
});
bot.command("help", async (ctx) => {
await ctx.reply(
`📚 *Помощь*
*Сигналы* — готовые идеи для сделок с точками входа, стоп-лосс и тейк-профит.
*Новости* — экономические события, влияющие на рынок (инфляция, ВВП, ставки).
*Свечи* — 12 основных паттернов для анализа графика.
*Риск* — расчёт лота для депозита $100 (риск 1-2% на сделку).
🌐 *Веб-версия:*
Открой дашборд в браузере: https://pages.git.vibe42.kz/Erlan/pomoschnik-po-torgam-na-fore/
⚠️ *Дисклеймер:*
Это не финансовая рекомендация. Торговля на форекс — высокий риск.`,
{ parse_mode: "Markdown" }
);
});
bot.command("signals", async (ctx) => {
const text = signals.map(s =>
`*${s.dir} ${s.pair}* — ${s.type}
Вход: ${s.entry}
Стоп: ${s.sl} | Тейк: ${s.tp}
Время: ${s.time}`
).join('\n\n');
await ctx.reply(
`🎯 *Торговые сигналы*\n\n${text}`,
{ parse_mode: "Markdown" }
);
});
bot.command("news", async (ctx) => {
const text = news.map(n =>
`${n.title}\n⏰ ${n.time} • ${n.impact}`
).join('\n\n');
await ctx.reply(
`📰 *Новости рынка*\n\n${text}`,
{ parse_mode: "Markdown" }
);
});
bot.command("candles", async (ctx) => {
const keyboard = {
reply_markup: {
inline_keyboard: candles.map(c => [
{ text: c.name.split(' ')[0] + ' ' + c.name.split(' ')[1], callback_data: `candle_${candles.indexOf(c)}` }
])
}
};
await ctx.reply(
'🕯️ *Свечные паттерны*\n\nВыберите паттерн:',
{ parse_mode: "Markdown", ...keyboard }
);
});
bot.command("risk", async (ctx) => {
await ctx.reply(
`🧮 *Калькулятор риска*
*Правила:*
• Риск на сделку: 1-2% депозита
• Стоп-лосс ОБЯЗАТЕЛЕН
• Соотношение риск/прибыль: минимум 1:2
*Пример для $100:*
Риск 2% = $2 на сделку
Стоп-лосс 20 пунктов
Лот = 0.01 (мини-лот)
Тейк-профит = 40 пунктов
Прибыль = $4
🌐 Полный калькулятор в веб-версии:
https://pages.git.vibe42.kz/Erlan/pomoschnik-po-torgam-na-fore/`,
{ parse_mode: "Markdown" }
);
});
bot.command("broadcast", async (ctx) => {
// Рассылка всем пользователям (только для админа)
if (ctx.from.id !== 123456789) {
return ctx.reply('❌ Нет доступа');
}
const message = ctx.message.text.replace('/broadcast ', '');
let count = 0;
for (const userId of users) {
try {
await bot.api.sendMessage(userId, message, { parse_mode: "Markdown" });
count++;
} catch (e) {
console.log(`Не удалось отправить ${userId}`);
}
}
await ctx.reply(`✅ Отправлено ${count} пользователям`);
});
// === ОБРАБОТКА КНОПОК ===
bot.on("callback_query:data", async (ctx) => {
const data = ctx.callbackQuery.data;
if (data.startsWith('candle_')) {
const index = parseInt(data.split('_')[1]);
const candle = candles[index];
await ctx.answerCallbackQuery();
await ctx.reply(
`*${candle.name}*\n\nТип: ${candle.type}\n\n${candle.desc}`,
{ parse_mode: "Markdown" }
);
}
});
// === ОБРАБОТКА ТЕКСТА ===
bot.on("message:text", async (ctx) => {
const text = ctx.message.text.toLowerCase();
if (text.includes('привет') || text.includes('здравствуй')) {
await ctx.reply(`👋 Привет, ${ctx.from.first_name}! Чем могу помочь?`);
}
if (text.includes('свеч') || text.includes('паттерн')) {
await ctx.reply('🕯️ Используй команду /candles для справочника свечей.');
}
if (text.includes('новост') || text.includes('событи')) {
await ctx.reply('📰 Используй команду /news для последних новостей.');
}
if (text.includes('сигнал') || text.includes('сделк')) {
await ctx.reply('🎯 Используй команду /signals для текущих сигналов.');
}
});
// === ЗАПУСК ===
bot.start().catch((err) => {
console.error("Ошибка запуска бота:", err);
});
console.log("🤖 Forex Bot запущен...");
// === РАССЫЛКА СИГНАЛОВ КАЖДЫЕ 4 ЧАСА ===
setInterval(async () => {
if (users.size === 0) return;
const signal = signals[Math.floor(Math.random() * signals.length)];
const message = `🎯 *Новый сигнал!*
${signal.dir} *${signal.pair}* — ${signal.type}
Вход: ${signal.entry}
Стоп: ${signal.sl}
Тейк: ${signal.tp}
⚠️ Это учебный сигнал. Реальные деньги — через брокера.`;
for (const userId of users) {
try {
await bot.api.sendMessage(userId, message, { parse_mode: "Markdown" });
} catch (e) {
console.log(`Не удалось отправить ${userId}`);
}
}
}, 4 * 60 * 60 * 1000); // 4 часа