Skip to content

Commit

Permalink
feat: Modify close CFD quotation and trade strategy
Browse files Browse the repository at this point in the history
  • Loading branch information
RexBearIU committed Mar 28, 2024
1 parent c07ac11 commit 054d8b9
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 48 deletions.
10 changes: 6 additions & 4 deletions src/strategies/strategies.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,12 @@ describe('StrategiesService', () => {
3210.38, 3221.28, 3220.03, 3219.03, 3220.01, 3224.01, 3228.11, 3212.89,
3211.79, 3224.31, 3216.85, 3207.8, 3224.44, 3220.49, 3212.7, 3219.26,
];
const spreadFee = 0.05;
const spreadFee = 5;
const ETHSuggestion = await strategiesService.getSuggestion('autoArima', {
currentPrice: 3219.26,
priceArray: ETHPriceArray,
spreadFee: spreadFee,
holdingStatus: 'WAIT',
});
expect(ETHSuggestion).toBe('BUY');
});
Expand Down Expand Up @@ -93,7 +95,7 @@ describe('StrategiesService', () => {
});

it('should backtest use csv', async () => {
console.log = () => {};
// console.log = () => {};
// Read the file
const csvContent = fs.readFileSync('src/strategies/ETH-USD.csv', 'utf8');
// Split the content into rows (assuming newline-separated rows)
Expand All @@ -114,7 +116,7 @@ describe('StrategiesService', () => {
// Info: (20240320 - Jacky) this is aim to sum the profit of all trades
const profitArray = tradeArray.map((trade) => trade.profit);
const sum = profitArray.reduce((total, profit) => total + profit, 0);
expect(sum).toBe(-67.06188301500049);
expect(sum).toBe(-1069.9531315100012);
});

it('should backtest use api', async () => {
Expand Down Expand Up @@ -166,6 +168,6 @@ describe('StrategiesService', () => {
// Info: (20240320 - Jacky) this is aim to sum the profit of all trades
const profitArray = tradeArray.map((trade) => trade.profit);
const sum = profitArray.reduce((total, profit) => total + profit, 0);
expect(sum).toBe(-214.9824);
expect(sum).toBe(-673.9419000000021);
});
});
16 changes: 6 additions & 10 deletions src/strategies/strategies.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ export class StrategiesService {
async backTesting(suggestion, stopLoss, takeProfit, priceData) {
let holdingStatus = 'WAIT';
let openPrice;
let openSpreadFee;
const priceArray: number[] = priceData;
const tradeArray = [];
for (let index = 30; index < priceArray.length; index++) {
Expand All @@ -39,13 +38,13 @@ export class StrategiesService {
if (holdingStatus !== 'WAIT') {
stopLossResult = await this.getStopLoss(stopLoss, {
openPrice: openPrice,
currentPrice: currentPrice + spreadFee,
currentPrice: currentPrice,
spreadFee: spreadFee,
holdingStatus: holdingStatus,
});
takeProfitResult = await this.getTakeProfit(takeProfit, {
openPrice: openPrice,
currentPrice: currentPrice + spreadFee,
currentPrice: currentPrice,
spreadFee: spreadFee,
holdingStatus: holdingStatus,
});
Expand All @@ -56,44 +55,41 @@ export class StrategiesService {
takeProfitResult === 'CLOSE'
) {
if (holdingStatus === 'BUY') {
const profit = currentPrice - openPrice - openSpreadFee;
const profit = currentPrice - spreadFee - openPrice;
tradeArray.push({
openPrice: openPrice,
price: currentPrice,
openSpreadFee: openSpreadFee,
profit: profit,
holdingStatus: holdingStatus,
tradeStrategy: 'CLOSE-BUY',
});
}
if (holdingStatus === 'SELL') {
const profit = openPrice - currentPrice - openSpreadFee;
const profit = openPrice - (currentPrice + spreadFee);
tradeArray.push({
openPrice: openPrice,
price: currentPrice,
profit: profit,
openSpreadFee: openSpreadFee,
holdingStatus: holdingStatus,
tradeStrategy: 'CLOSE-SELL',
});
}
holdingStatus = 'WAIT';
openPrice = null;
openSpreadFee = null;
continue;
}
if (suggestionResult !== 'WAIT' && holdingStatus === 'WAIT') {
openSpreadFee = spreadFee;
holdingStatus = suggestionResult;
openPrice = JSON.parse(JSON.stringify(currentPrice));
tradeArray.push({
openPrice: openPrice,
price: currentPrice,
profit: 0,
openSpreadFee: openSpreadFee,
holdingStatus: holdingStatus,
suggestionResult: suggestionResult,
});
}
continue;
}
return { tradeArray };
}
Expand Down
32 changes: 17 additions & 15 deletions src/strategies/strategy/autoArima.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,15 @@ export function suggestion(data: {
let suggestion = 'WAIT';
const arima = new ARIMA('auto');
arima.train(data.priceArray);
const AbsspreadFee = Math.abs(data.spreadFee);
const arimaPredict = arima.predict(36);
// const AbsspreadFee = Math.abs(data.spreadFee);
const arimaPredict = arima.predict(15);
const predict: number[] = arimaPredict[0];
const predictMax = Math.max(...predict);
const predictMin = Math.min(...predict);
const predictProfit = AbsspreadFee * 2.2;
// const predictProfit = AbsspreadFee * 2.8;
const currentPrice = data.currentPrice;
if (predictMax - currentPrice > predictProfit) {
if (predict[predict.length - 1] > currentPrice) {
suggestion = 'BUY';
}
if (currentPrice - predictMin > predictProfit) {
if (predict[predict.length - 1] < currentPrice) {
suggestion = 'SELL';
}
if (suggestion === 'WAIT') {
Expand All @@ -40,18 +38,20 @@ export function takeProfit(data: {
spreadFee: number;
holdingStatus: string;
}) {
const AbsOpenSpreadFee = Math.abs(data.spreadFee);
const AbsSpreadFee = Math.abs(data.spreadFee);
const openPrice = data.openPrice;
const currentPrice = data.currentPrice;
const takeProfit = AbsOpenSpreadFee * 1.8;
const takeProfit = AbsSpreadFee * 1.5;
const holdingStatus = data.holdingStatus;
if (holdingStatus === 'BUY') {
if (currentPrice - openPrice > takeProfit) {
// Info: (20240328 - Jacky) Current Sell price is higher than the open Buy price
if (currentPrice - AbsSpreadFee - openPrice > takeProfit) {
return 'CLOSE';
}
}
if (holdingStatus === 'SELL') {
if (openPrice - currentPrice < takeProfit) {
// Info: (20240328 - Jacky) Current Buy price is lower than the open Sell price
if (openPrice - (currentPrice + AbsSpreadFee) > takeProfit) {
return 'CLOSE';
}
}
Expand All @@ -63,18 +63,20 @@ export function stopLoss(data: {
spreadFee: number;
holdingStatus: string;
}) {
const AbsOpenSpreadFee = Math.abs(data.spreadFee);
const AbsSpreadFee = Math.abs(data.spreadFee);
const openPrice = data.openPrice;
const currentPrice = data.currentPrice;
const stopLoss = AbsOpenSpreadFee * 0.6;
const stopLoss = AbsSpreadFee * 0.7;
const holdingStatus = data.holdingStatus;
if (holdingStatus === 'BUY') {
if (openPrice - currentPrice > stopLoss) {
// Info: (20240328 - Jacky) Current Buy price is lower than the open Buy price
if (openPrice - (currentPrice + AbsSpreadFee) > stopLoss) {
return 'CLOSE';
}
}
if (holdingStatus === 'SELL') {
if (currentPrice - openPrice > stopLoss) {
// Info: (20240328 - Jacky) Current Sell price is higher than the open Sell price
if (currentPrice - AbsSpreadFee - openPrice > stopLoss) {
return 'CLOSE';
}
}
Expand Down
1 change: 0 additions & 1 deletion src/tradebot/entities/tradebot.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ export class Tradebot {
holdingInstId: string;
positionId: string;
openPrice: number;
absSpreadFee: number;
endAsset: myAsset;
isRunning: boolean;
timer?: NodeJS.Timeout;
Expand Down
35 changes: 17 additions & 18 deletions src/tradebot/tradebot.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { DewtService } from '../dewt/dewt.service';
import { PriceTickerService } from '../price_ticker/price_ticker.service';
import { StrategiesService } from '../strategies/strategies.service';
import { TransactionService } from '../transaction/transaction.service';
import { QuotationDto } from '../price_ticker/dto/quotation.dto';

@Injectable()
export class TradebotService {
Expand Down Expand Up @@ -135,22 +134,13 @@ export class TradebotService {
' purchase strategy',
);
try {
let quotation: QuotationDto;
if (tradebot.holdingStatus === 'WAIT') {
this.logger.log('Tradebot ' + tradebot.id + ' hasn`t holding position');
quotation = await this.priceTickerService.getCFDQuotation(instId);
} else {
quotation = await this.priceTickerService.getCFDQuotation(
tradebot.holdingStatus,
tradebot.holdingInstId,
);
}
let quotation = await this.priceTickerService.getCFDQuotation(instId);
const priceArray = await this.priceTickerService.getCandlesticks(instId);
const suggestion = await this.strategiesService.getSuggestion(
tradebot.suggestion,
{
priceArray: priceArray,
currentPrice: quotation.data.price,
currentPrice: quotation.data.spotPrice,
spreadFee: quotation.data.spreadFee,
holdingStatus: tradebot.holdingStatus,
},
Expand All @@ -159,17 +149,17 @@ export class TradebotService {
tradebot.takeProfit,
{
openPrice: tradebot.openPrice,
currentPrice: quotation.data.price,
spreadFee: tradebot.absSpreadFee,
currentPrice: quotation.data.spotPrice,
spreadFee: quotation.data.spreadFee,
holdingStatus: tradebot.holdingStatus,
},
);
const stopLoss = await this.strategiesService.getStopLoss(
tradebot.stopLoss,
{
openPrice: tradebot.openPrice,
currentPrice: quotation.data.price,
spreadFee: tradebot.absSpreadFee,
currentPrice: quotation.data.spotPrice,
spreadFee: quotation.data.spreadFee,
holdingStatus: tradebot.holdingStatus,
},
);
Expand All @@ -191,6 +181,17 @@ export class TradebotService {
'create dewt for tradebot ' + tradebot.id + ' register failed',
);
}
if (tradebot.holdingStatus === 'BUY') {
quotation = await this.priceTickerService.getCFDQuotation(
'SELL',
tradebot.holdingInstId,
);
} else if (tradebot.holdingStatus === 'SELL') {
quotation = await this.priceTickerService.getCFDQuotation(
'BUY',
tradebot.holdingInstId,
);
}
const closeCFDOrderDto =
await this.trancsactionService.closeCFDOrderDTO(
quotation,
Expand Down Expand Up @@ -218,7 +219,6 @@ export class TradebotService {
tradebot.updated_at = new Date();
tradebot.positionId = null;
tradebot.openPrice = null;
tradebot.absSpreadFee = null;
tradebot.currentAsset = await this.userService.getMyAsset(
tradebot.dewt,
);
Expand Down Expand Up @@ -272,7 +272,6 @@ export class TradebotService {
tradebot.holdingInstId = instId;
tradebot.positionId = createCFDOrder.data.orderSnapshot.id;
tradebot.openPrice = quotation.data.price;
tradebot.absSpreadFee = Math.abs(quotation.data.spreadFee);
tradebot.updated_at = new Date();
tradebot.currentAsset = await this.userService.getMyAsset(
tradebot.dewt,
Expand Down

0 comments on commit 054d8b9

Please sign in to comment.