update
This commit is contained in:
parent
d8f8b04943
commit
bda0518a6a
1 changed files with 71 additions and 32 deletions
|
|
@ -1,6 +1,10 @@
|
||||||
import { EMA, MACD } from "technicalindicators";
|
import { BollingerBands, EMA, MACD } from "technicalindicators";
|
||||||
import { Candle } from "../dao/candles";
|
import { Candle } from "../dao/candles";
|
||||||
import { analyzeCandleSequence, isHighVolatilityCandle, isPinBar } from "../helpers/candles";
|
import {
|
||||||
|
analyzeCandleSequence,
|
||||||
|
isHighVolatilityCandle,
|
||||||
|
isPinBar,
|
||||||
|
} from "../helpers/candles";
|
||||||
import { Analysis } from "../dao/analysis";
|
import { Analysis } from "../dao/analysis";
|
||||||
import { KlineIntervalV3 } from "bybit-api";
|
import { KlineIntervalV3 } from "bybit-api";
|
||||||
import { Order } from "../dao/order";
|
import { Order } from "../dao/order";
|
||||||
|
|
@ -48,6 +52,14 @@ export class IndicatorService {
|
||||||
SimpleMASignal: false,
|
SimpleMASignal: false,
|
||||||
reversedInput: true,
|
reversedInput: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const bb = BollingerBands.calculate({
|
||||||
|
period: 20,
|
||||||
|
stdDev: 2,
|
||||||
|
values: close,
|
||||||
|
reversedInput: true,
|
||||||
|
});
|
||||||
|
|
||||||
const candle = candles[0];
|
const candle = candles[0];
|
||||||
|
|
||||||
const analysis: Analysis = {
|
const analysis: Analysis = {
|
||||||
|
|
@ -65,9 +77,9 @@ export class IndicatorService {
|
||||||
isSell: false,
|
isSell: false,
|
||||||
isTouch200: false,
|
isTouch200: false,
|
||||||
isReverse200: false,
|
isReverse200: false,
|
||||||
lowHight: wave.lowOrHighPrice,
|
lowHight: wave.lowOrHighPrice,
|
||||||
numberTouch200: wave.numberTouchEma,
|
numberTouch200: wave.numberTouchEma,
|
||||||
numberMacdCrossUp: wave.numberMacdCrossUp,
|
numberMacdCrossUp: wave.numberMacdCrossUp,
|
||||||
numberMacdCrossDown: wave.numberMacdCrossDown,
|
numberMacdCrossDown: wave.numberMacdCrossDown,
|
||||||
isMacdUpper: false,
|
isMacdUpper: false,
|
||||||
isMacdLower: false,
|
isMacdLower: false,
|
||||||
|
|
@ -76,26 +88,22 @@ export class IndicatorService {
|
||||||
if (ema34[0] > ema200[0]) {
|
if (ema34[0] > ema200[0]) {
|
||||||
if (wave.trend === "Bearish") {
|
if (wave.trend === "Bearish") {
|
||||||
analysis.numberTouch200 = 0;
|
analysis.numberTouch200 = 0;
|
||||||
|
analysis.numberMacdCrossDown = 0;
|
||||||
|
analysis.numberMacdCrossUp = 1;
|
||||||
}
|
}
|
||||||
analysis.emaDirection = "Bullish";
|
analysis.emaDirection = "Bullish";
|
||||||
} else {
|
} else {
|
||||||
if (wave.trend === "Bullish") {
|
if (wave.trend === "Bullish") {
|
||||||
analysis.numberTouch200 = 0;
|
analysis.numberTouch200 = 0;
|
||||||
|
analysis.numberMacdCrossDown = 1;
|
||||||
|
analysis.numberMacdCrossUp = 0;
|
||||||
}
|
}
|
||||||
analysis.emaDirection = "Bearish";
|
analysis.emaDirection = "Bearish";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (macd[0].MACD! > macd[0].signal!) {
|
if (macd[0].MACD! > macd[0].signal!) {
|
||||||
if (wave.trend === "Bearish") {
|
|
||||||
analysis.numberMacdCrossUp = 0;
|
|
||||||
analysis.numberMacdCrossDown = 0;
|
|
||||||
}
|
|
||||||
analysis.macdDirection = "Bullish";
|
analysis.macdDirection = "Bullish";
|
||||||
} else {
|
} else {
|
||||||
if (wave.trend === "Bullish") {
|
|
||||||
analysis.numberMacdCrossDown = 0;
|
|
||||||
analysis.numberMacdCrossUp = 0;
|
|
||||||
}
|
|
||||||
analysis.macdDirection = "Bearish";
|
analysis.macdDirection = "Bearish";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -118,7 +126,10 @@ export class IndicatorService {
|
||||||
if (macd[0].MACD! > macd[0].signal! && macd[1].MACD! < macd[1].signal!) {
|
if (macd[0].MACD! > macd[0].signal! && macd[1].MACD! < macd[1].signal!) {
|
||||||
analysis.isMacdCrossUp = true;
|
analysis.isMacdCrossUp = true;
|
||||||
analysis.numberMacdCrossUp++;
|
analysis.numberMacdCrossUp++;
|
||||||
} else if (macd[0].MACD! < macd[0].signal! && macd[1].MACD! > macd[1].signal!) {
|
} else if (
|
||||||
|
macd[0].MACD! < macd[0].signal! &&
|
||||||
|
macd[1].MACD! > macd[1].signal!
|
||||||
|
) {
|
||||||
analysis.isMacdCrossDown = true;
|
analysis.isMacdCrossDown = true;
|
||||||
analysis.numberMacdCrossDown++;
|
analysis.numberMacdCrossDown++;
|
||||||
}
|
}
|
||||||
|
|
@ -159,7 +170,11 @@ export class IndicatorService {
|
||||||
analysis.isTouch200 = true;
|
analysis.isTouch200 = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (candle.open < ema200[0] && candle.close > ema200[0] && analysis.emaDirection === "Bullish") {
|
if (
|
||||||
|
candle.open < ema200[0] &&
|
||||||
|
candle.close > ema200[0] &&
|
||||||
|
analysis.emaDirection === "Bullish"
|
||||||
|
) {
|
||||||
const candlesCheck = [candles[3], candles[2], candles[1], candles[0]];
|
const candlesCheck = [candles[3], candles[2], candles[1], candles[0]];
|
||||||
const ema200Check = [ema200[3], ema200[2], ema200[1], ema200[0]];
|
const ema200Check = [ema200[3], ema200[2], ema200[1], ema200[0]];
|
||||||
const candleCheck = candlesCheck.find(
|
const candleCheck = candlesCheck.find(
|
||||||
|
|
@ -171,7 +186,11 @@ export class IndicatorService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (candle.open > ema200[0] && candle.close < ema200[0] && analysis.emaDirection === "Bearish") {
|
if (
|
||||||
|
candle.open > ema200[0] &&
|
||||||
|
candle.close < ema200[0] &&
|
||||||
|
analysis.emaDirection === "Bearish"
|
||||||
|
) {
|
||||||
const candlesCheck = [candles[3], candles[2], candles[1], candles[0]];
|
const candlesCheck = [candles[3], candles[2], candles[1], candles[0]];
|
||||||
const ema200Check = [ema200[3], ema200[2], ema200[1], ema200[0]];
|
const ema200Check = [ema200[3], ema200[2], ema200[1], ema200[0]];
|
||||||
const candleCheck = candlesCheck.find(
|
const candleCheck = candlesCheck.find(
|
||||||
|
|
@ -188,10 +207,20 @@ export class IndicatorService {
|
||||||
return analysis;
|
return analysis;
|
||||||
}
|
}
|
||||||
|
|
||||||
makeOrder(analysis: Analysis, candles: Candle[], side: "buy" | "sell"): Order {
|
makeOrder(
|
||||||
|
analysis: Analysis,
|
||||||
|
candles: Candle[],
|
||||||
|
side: "buy" | "sell"
|
||||||
|
): Order {
|
||||||
const last10Candles = candles.slice(0, 12);
|
const last10Candles = candles.slice(0, 12);
|
||||||
const lowestPrice = last10Candles.reduce((min, c) => Math.min(min, c.low), Number.MAX_SAFE_INTEGER);
|
const lowestPrice = last10Candles.reduce(
|
||||||
const highestPrice = last10Candles.reduce((max, c) => Math.max(max, c.high), Number.MIN_SAFE_INTEGER);
|
(min, c) => Math.min(min, c.low),
|
||||||
|
Number.MAX_SAFE_INTEGER
|
||||||
|
);
|
||||||
|
const highestPrice = last10Candles.reduce(
|
||||||
|
(max, c) => Math.max(max, c.high),
|
||||||
|
Number.MIN_SAFE_INTEGER
|
||||||
|
);
|
||||||
const order: Order = {
|
const order: Order = {
|
||||||
symbol: analysis.symbol,
|
symbol: analysis.symbol,
|
||||||
side,
|
side,
|
||||||
|
|
@ -202,7 +231,11 @@ export class IndicatorService {
|
||||||
return order;
|
return order;
|
||||||
}
|
}
|
||||||
|
|
||||||
handleEvent(analysis: Analysis, candles: Candle[], eventHandler: EventHandler) {
|
handleEvent(
|
||||||
|
analysis: Analysis,
|
||||||
|
candles: Candle[],
|
||||||
|
eventHandler: EventHandler
|
||||||
|
) {
|
||||||
if (analysis.isTouch200 && analysis.emaDirection === "Bullish") {
|
if (analysis.isTouch200 && 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");
|
||||||
|
|
@ -211,34 +244,42 @@ export class IndicatorService {
|
||||||
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");
|
||||||
}
|
}
|
||||||
if (analysis.isMacdCrossUp && analysis.isMacdUpper) {
|
if (analysis.isMacdCrossUp && analysis.emaDirection === "Bullish") {
|
||||||
const order = this.makeOrder(analysis, candles, "buy");
|
const order = this.makeOrder(analysis, candles, "buy");
|
||||||
eventHandler.onBuy(order, "Follow trend MACD Cross Up");
|
eventHandler.onBuy(order, "Follow trend MACD Cross Up");
|
||||||
}
|
}
|
||||||
if (analysis.isMacdCrossDown && analysis.isMacdLower) {
|
if (analysis.isMacdCrossDown && analysis.emaDirection === "Bearish") {
|
||||||
const order = this.makeOrder(analysis, candles, "sell");
|
const order = this.makeOrder(analysis, candles, "sell");
|
||||||
eventHandler.onSell(order, "Follow trend MACD Cross Down");
|
eventHandler.onSell(order, "Follow trend MACD Cross Down");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (analysis.isMacdCrossUp && analysis.isMacdLower && analysis.numberMacdCrossUp >= 2) {
|
if (
|
||||||
|
analysis.isMacdCrossUp &&
|
||||||
|
analysis.isMacdLower &&
|
||||||
|
analysis.numberMacdCrossUp >= 2
|
||||||
|
) {
|
||||||
const order = this.makeOrder(analysis, candles, "buy");
|
const order = this.makeOrder(analysis, candles, "buy");
|
||||||
eventHandler.onBuy(order, "Counter trend rủi ro cao MACD Cross Up");
|
eventHandler.onBuy(order, "Counter trend rủi ro cao MACD Cross Up");
|
||||||
}
|
}
|
||||||
if (analysis.isMacdCrossDown && analysis.isMacdUpper && analysis.numberMacdCrossDown >= 2) {
|
if (
|
||||||
|
analysis.isMacdCrossDown &&
|
||||||
|
analysis.isMacdUpper &&
|
||||||
|
analysis.numberMacdCrossDown >= 2
|
||||||
|
) {
|
||||||
const order = this.makeOrder(analysis, candles, "sell");
|
const order = this.makeOrder(analysis, candles, "sell");
|
||||||
eventHandler.onSell(order, "Counter trend rủi ro cao MACD Cross Down");
|
eventHandler.onSell(order, "Counter trend rủi ro cao MACD Cross Down");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lấy bản ghi wave theo symbol và interval
|
* Lấy bản ghi wave theo symbol và interval
|
||||||
*/
|
*/
|
||||||
async getWave(symbol: string, interval: string) {
|
async getWave(symbol: string, interval: string) {
|
||||||
const { data, error } = await supabase
|
const { data, error } = await supabase
|
||||||
.from('waves')
|
.from("waves")
|
||||||
.select('*')
|
.select("*")
|
||||||
.eq('symbol', symbol)
|
.eq("symbol", symbol)
|
||||||
.eq('interval', interval)
|
.eq("interval", interval)
|
||||||
.single();
|
.single();
|
||||||
if (error) return null;
|
if (error) return null;
|
||||||
return data;
|
return data;
|
||||||
|
|
@ -249,10 +290,8 @@ export class IndicatorService {
|
||||||
*/
|
*/
|
||||||
async upsertWave(wave: Wave) {
|
async upsertWave(wave: Wave) {
|
||||||
const { data, error } = await supabase
|
const { data, error } = await supabase
|
||||||
.from('waves')
|
.from("waves")
|
||||||
.upsert([
|
.upsert([wave], { onConflict: "symbol,interval" });
|
||||||
wave
|
|
||||||
], { onConflict: 'symbol,interval' });
|
|
||||||
if (error) {
|
if (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue