This commit is contained in:
KienVT9 2025-07-18 10:07:11 +07:00
commit 272ba19977
3 changed files with 75 additions and 30 deletions

View file

@ -4,6 +4,7 @@ export interface Position {
entry: number; entry: number;
leverage: number; leverage: number;
volume: number; volume: number;
profit: number; sl: number;
profitPercentage: number; tp: number;
status: string;
} }

View file

@ -16,8 +16,6 @@ const bybitService = new BybitService(
false false
); );
export const eventHandlerFuture: EventHandler = { export const eventHandlerFuture: EventHandler = {
onBuy: (order: Order, reason: string) => { onBuy: (order: Order, reason: string) => {
sendMessage(`Future Buy ${order.symbol} ${order.interval}M sendMessage(`Future Buy ${order.symbol} ${order.interval}M
@ -35,7 +33,8 @@ export const eventHandlerFuture: EventHandler = {
side: "Buy", side: "Buy",
orderType: "Limit", orderType: "Limit",
price: Number(order.entry).toFixed(2), price: Number(order.entry).toFixed(2),
qty: '1', stopLoss: Number(order.stopLoss).toFixed(2),
qty: "1",
}); });
console.log( console.log(
@ -57,13 +56,17 @@ export const eventHandlerFuture: EventHandler = {
side: "Sell", side: "Sell",
orderType: "Limit", orderType: "Limit",
price: Number(order.entry).toFixed(2), price: Number(order.entry).toFixed(2),
qty: '1', stopLoss: Number(order.stopLoss).toFixed(2),
qty: "1",
}); });
console.log( console.log(
`Sell ${order.symbol} ${order.interval}M ${reason} ${order.entry}` `Sell ${order.symbol} ${order.interval}M ${reason} ${order.entry}`
); );
}, },
onEvent: async (eventType: EventType, {candle, analysis}: {candle: Candle, analysis: Analysis}) => { onEvent: async (
eventType: EventType,
{ candle, analysis }: { candle: Candle; analysis: Analysis }
) => {
if (eventType === "HighVolatility") { if (eventType === "HighVolatility") {
const positions = await bybitService.listPositions({ const positions = await bybitService.listPositions({
category: "linear", category: "linear",
@ -78,10 +81,15 @@ export const eventHandlerFuture: EventHandler = {
symbol: analysis.symbol, symbol: analysis.symbol,
side: "Sell", side: "Sell",
orderType: "Limit", orderType: "Limit",
price: candle.close > analysis.currentBB.upper ? Number(candle.close).toFixed(2) : Number(analysis.currentBB.upper).toFixed(2), price:
candle.close > analysis.currentBB.upper
? Number(candle.close).toFixed(2)
: Number(analysis.currentBB.upper).toFixed(2),
qty: halfSize, qty: halfSize,
}); });
sendMessage(`Future Căt nửa ${analysis.symbol} ${analysis.interval}M ${analysis.currentBB.upper} ${halfSize}`); sendMessage(
`Future Căt nửa ${analysis.symbol} ${analysis.interval}M ${analysis.currentBB.upper} ${halfSize}`
);
} }
if (position.side === "Sell" && analysis.isUnderBbLower && candle.close < candle.open) { if (position.side === "Sell" && analysis.isUnderBbLower && candle.close < candle.open) {
const halfSize = (Number(position.size) / 2).toFixed(2); const halfSize = (Number(position.size) / 2).toFixed(2);
@ -90,10 +98,15 @@ export const eventHandlerFuture: EventHandler = {
symbol: analysis.symbol, symbol: analysis.symbol,
side: "Buy", side: "Buy",
orderType: "Limit", orderType: "Limit",
price: candle.close < analysis.currentBB.lower ? Number(candle.close).toFixed(2) : Number(analysis.currentBB.lower).toFixed(2), price:
candle.close < analysis.currentBB.lower
? Number(candle.close).toFixed(2)
: Number(analysis.currentBB.lower).toFixed(2),
qty: halfSize, qty: halfSize,
}); });
sendMessage(`Future Căt nửa ${analysis.symbol} ${analysis.interval}M ${analysis.currentBB.lower} ${halfSize}`); sendMessage(
`Future Căt nửa ${analysis.symbol} ${analysis.interval}M ${analysis.currentBB.lower} ${halfSize}`
);
} }
} }
} }
@ -117,7 +130,7 @@ const eventHandlerSpot: EventHandler = {
side: "Buy", side: "Buy",
orderType: "Limit", orderType: "Limit",
price: Number(order.entry).toFixed(2), price: Number(order.entry).toFixed(2),
qty: '1', qty: "1",
}); });
console.log( console.log(
@ -134,8 +147,10 @@ const eventHandlerSpot: EventHandler = {
reason: ${reason} reason: ${reason}
`); `);
}, },
onEvent: async (eventType: EventType, {candle, analysis}: {candle: Candle, analysis: Analysis}) => { onEvent: async (
}, eventType: EventType,
{ candle, analysis }: { candle: Candle; analysis: Analysis }
) => {},
}; };
const eventHandlerNotification: EventHandler = { const eventHandlerNotification: EventHandler = {
@ -163,8 +178,10 @@ const eventHandlerNotification: EventHandler = {
reason: ${reason} reason: ${reason}
`); `);
}, },
onEvent: async (eventType: EventType, {candle, analysis}: {candle: Candle, analysis: Analysis}) => { onEvent: async (
}, eventType: EventType,
{ candle, analysis }: { candle: Candle; analysis: Analysis }
) => {},
}; };
createCandleAnalysisSchedule("ETHUSDT", "15", eventHandlerFuture); createCandleAnalysisSchedule("ETHUSDT", "15", eventHandlerFuture);

View file

@ -11,12 +11,23 @@ import { Order } from "../dao/order";
import { supabase } from "./supabaseService"; import { supabase } from "./supabaseService";
import { Wave } from "../dao/wave"; import { Wave } from "../dao/wave";
export type EventType = "HighVolatility" | "PinBar" | "EmaCross" | "MacdCross" | "MacdCrossUp" | "MacdCrossDown" | "Touch200" | "Reverse200"; export type EventType =
| "HighVolatility"
| "PinBar"
| "EmaCross"
| "MacdCross"
| "MacdCrossUp"
| "MacdCrossDown"
| "Touch200"
| "Reverse200";
export interface EventHandler { export interface EventHandler {
onBuy: (candle: Order, reason: string) => void; onBuy: (candle: Order, reason: string) => void;
onSell: (candle: Order, reason: string) => void; onSell: (candle: Order, reason: string) => void;
onEvent: (eventType: EventType, {candle, analysis}: {candle: Candle, analysis: Analysis}) => void; onEvent: (
eventType: EventType,
{ candle, analysis }: { candle: Candle; analysis: Analysis }
) => void;
} }
export class IndicatorService { export class IndicatorService {
@ -36,7 +47,7 @@ export class IndicatorService {
} }
let close = candles.map((c) => c.close); let close = candles.map((c) => c.close);
const ema34 = EMA.calculate({ const ema34 = EMA.calculate({
period: 20, period: 34,
values: close, values: close,
reversedInput: true, reversedInput: true,
}); });
@ -244,19 +255,29 @@ export class IndicatorService {
); );
let entry = candles[0].close; let entry = candles[0].close;
if (side === "buy") { if (side === "buy") {
if (analysis.currentBB.upper < Math.max(candles[0].close, candles[0].open)) { if (
analysis.currentBB.upper < Math.max(candles[0].close, candles[0].open)
) {
entry = analysis.currentBB.upper; entry = analysis.currentBB.upper;
} }
if (analysis.currentBB.lower < candles[0].open && analysis.currentBB.lower > candles[0].close) { if (
analysis.currentBB.lower < candles[0].open &&
analysis.currentBB.lower > candles[0].close
) {
entry = analysis.currentBB.lower; entry = analysis.currentBB.lower;
} }
} }
if (side === "sell") { if (side === "sell") {
if (analysis.currentBB.lower > Math.min(candles[0].close, candles[0].open)) { if (
analysis.currentBB.lower > Math.min(candles[0].close, candles[0].open)
) {
entry = analysis.currentBB.lower; entry = analysis.currentBB.lower;
} }
if (analysis.currentBB.upper > candles[0].open && analysis.currentBB.upper < candles[0].close) { if (
analysis.currentBB.upper > candles[0].open &&
analysis.currentBB.upper < candles[0].close
) {
entry = analysis.currentBB.upper; entry = analysis.currentBB.upper;
} }
} }
@ -277,12 +298,18 @@ export class IndicatorService {
candles: Candle[], candles: Candle[],
eventHandler: EventHandler eventHandler: EventHandler
) { ) {
if ((analysis.isTouch200 || analysis.isReverse200) && analysis.emaDirection === "Bullish") { if (
(analysis.isTouch200 || analysis.isReverse200) &&
analysis.emaDirection === "Bullish"
) {
const order = this.makeOrder(analysis, candles, "buy"); const order = this.makeOrder(analysis, candles, "buy");
eventHandler.onBuy(order, "Follow trend EMA Touch 200"); eventHandler.onBuy(order, "Follow trend EMA Touch 200");
return; return;
} }
if ((analysis.isTouch200 || analysis.isReverse200) && analysis.emaDirection === "Bearish") { if (
(analysis.isTouch200 || analysis.isReverse200) &&
analysis.emaDirection === "Bearish"
) {
const order = this.makeOrder(analysis, candles, "sell"); const order = this.makeOrder(analysis, candles, "sell");
eventHandler.onSell(order, "Follow trend EMA Touch 200"); eventHandler.onSell(order, "Follow trend EMA Touch 200");
return; return;
@ -316,7 +343,7 @@ export class IndicatorService {
} }
if (analysis.isHighVolatility) { if (analysis.isHighVolatility) {
eventHandler.onEvent("HighVolatility", {candle: candles[0], analysis}); eventHandler.onEvent("HighVolatility", { candle: candles[0], analysis });
} }
} }