Skip to content

Commit 054d8b9

Browse files
committed
feat: Modify close CFD quotation and trade strategy
1 parent c07ac11 commit 054d8b9

File tree

5 files changed

+46
-48
lines changed

5 files changed

+46
-48
lines changed

src/strategies/strategies.service.spec.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,12 @@ describe('StrategiesService', () => {
5656
3210.38, 3221.28, 3220.03, 3219.03, 3220.01, 3224.01, 3228.11, 3212.89,
5757
3211.79, 3224.31, 3216.85, 3207.8, 3224.44, 3220.49, 3212.7, 3219.26,
5858
];
59-
const spreadFee = 0.05;
59+
const spreadFee = 5;
6060
const ETHSuggestion = await strategiesService.getSuggestion('autoArima', {
61+
currentPrice: 3219.26,
6162
priceArray: ETHPriceArray,
6263
spreadFee: spreadFee,
64+
holdingStatus: 'WAIT',
6365
});
6466
expect(ETHSuggestion).toBe('BUY');
6567
});
@@ -93,7 +95,7 @@ describe('StrategiesService', () => {
9395
});
9496

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

120122
it('should backtest use api', async () => {
@@ -166,6 +168,6 @@ describe('StrategiesService', () => {
166168
// Info: (20240320 - Jacky) this is aim to sum the profit of all trades
167169
const profitArray = tradeArray.map((trade) => trade.profit);
168170
const sum = profitArray.reduce((total, profit) => total + profit, 0);
169-
expect(sum).toBe(-214.9824);
171+
expect(sum).toBe(-673.9419000000021);
170172
});
171173
});

src/strategies/strategies.service.ts

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ export class StrategiesService {
2222
async backTesting(suggestion, stopLoss, takeProfit, priceData) {
2323
let holdingStatus = 'WAIT';
2424
let openPrice;
25-
let openSpreadFee;
2625
const priceArray: number[] = priceData;
2726
const tradeArray = [];
2827
for (let index = 30; index < priceArray.length; index++) {
@@ -39,13 +38,13 @@ export class StrategiesService {
3938
if (holdingStatus !== 'WAIT') {
4039
stopLossResult = await this.getStopLoss(stopLoss, {
4140
openPrice: openPrice,
42-
currentPrice: currentPrice + spreadFee,
41+
currentPrice: currentPrice,
4342
spreadFee: spreadFee,
4443
holdingStatus: holdingStatus,
4544
});
4645
takeProfitResult = await this.getTakeProfit(takeProfit, {
4746
openPrice: openPrice,
48-
currentPrice: currentPrice + spreadFee,
47+
currentPrice: currentPrice,
4948
spreadFee: spreadFee,
5049
holdingStatus: holdingStatus,
5150
});
@@ -56,44 +55,41 @@ export class StrategiesService {
5655
takeProfitResult === 'CLOSE'
5756
) {
5857
if (holdingStatus === 'BUY') {
59-
const profit = currentPrice - openPrice - openSpreadFee;
58+
const profit = currentPrice - spreadFee - openPrice;
6059
tradeArray.push({
6160
openPrice: openPrice,
6261
price: currentPrice,
63-
openSpreadFee: openSpreadFee,
6462
profit: profit,
6563
holdingStatus: holdingStatus,
6664
tradeStrategy: 'CLOSE-BUY',
6765
});
6866
}
6967
if (holdingStatus === 'SELL') {
70-
const profit = openPrice - currentPrice - openSpreadFee;
68+
const profit = openPrice - (currentPrice + spreadFee);
7169
tradeArray.push({
7270
openPrice: openPrice,
7371
price: currentPrice,
7472
profit: profit,
75-
openSpreadFee: openSpreadFee,
7673
holdingStatus: holdingStatus,
7774
tradeStrategy: 'CLOSE-SELL',
7875
});
7976
}
8077
holdingStatus = 'WAIT';
8178
openPrice = null;
82-
openSpreadFee = null;
79+
continue;
8380
}
8481
if (suggestionResult !== 'WAIT' && holdingStatus === 'WAIT') {
85-
openSpreadFee = spreadFee;
8682
holdingStatus = suggestionResult;
8783
openPrice = JSON.parse(JSON.stringify(currentPrice));
8884
tradeArray.push({
8985
openPrice: openPrice,
9086
price: currentPrice,
9187
profit: 0,
92-
openSpreadFee: openSpreadFee,
9388
holdingStatus: holdingStatus,
9489
suggestionResult: suggestionResult,
9590
});
9691
}
92+
continue;
9793
}
9894
return { tradeArray };
9995
}

src/strategies/strategy/autoArima.ts

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,15 @@ export function suggestion(data: {
99
let suggestion = 'WAIT';
1010
const arima = new ARIMA('auto');
1111
arima.train(data.priceArray);
12-
const AbsspreadFee = Math.abs(data.spreadFee);
13-
const arimaPredict = arima.predict(36);
12+
// const AbsspreadFee = Math.abs(data.spreadFee);
13+
const arimaPredict = arima.predict(15);
1414
const predict: number[] = arimaPredict[0];
15-
const predictMax = Math.max(...predict);
16-
const predictMin = Math.min(...predict);
17-
const predictProfit = AbsspreadFee * 2.2;
15+
// const predictProfit = AbsspreadFee * 2.8;
1816
const currentPrice = data.currentPrice;
19-
if (predictMax - currentPrice > predictProfit) {
17+
if (predict[predict.length - 1] > currentPrice) {
2018
suggestion = 'BUY';
2119
}
22-
if (currentPrice - predictMin > predictProfit) {
20+
if (predict[predict.length - 1] < currentPrice) {
2321
suggestion = 'SELL';
2422
}
2523
if (suggestion === 'WAIT') {
@@ -40,18 +38,20 @@ export function takeProfit(data: {
4038
spreadFee: number;
4139
holdingStatus: string;
4240
}) {
43-
const AbsOpenSpreadFee = Math.abs(data.spreadFee);
41+
const AbsSpreadFee = Math.abs(data.spreadFee);
4442
const openPrice = data.openPrice;
4543
const currentPrice = data.currentPrice;
46-
const takeProfit = AbsOpenSpreadFee * 1.8;
44+
const takeProfit = AbsSpreadFee * 1.5;
4745
const holdingStatus = data.holdingStatus;
4846
if (holdingStatus === 'BUY') {
49-
if (currentPrice - openPrice > takeProfit) {
47+
// Info: (20240328 - Jacky) Current Sell price is higher than the open Buy price
48+
if (currentPrice - AbsSpreadFee - openPrice > takeProfit) {
5049
return 'CLOSE';
5150
}
5251
}
5352
if (holdingStatus === 'SELL') {
54-
if (openPrice - currentPrice < takeProfit) {
53+
// Info: (20240328 - Jacky) Current Buy price is lower than the open Sell price
54+
if (openPrice - (currentPrice + AbsSpreadFee) > takeProfit) {
5555
return 'CLOSE';
5656
}
5757
}
@@ -63,18 +63,20 @@ export function stopLoss(data: {
6363
spreadFee: number;
6464
holdingStatus: string;
6565
}) {
66-
const AbsOpenSpreadFee = Math.abs(data.spreadFee);
66+
const AbsSpreadFee = Math.abs(data.spreadFee);
6767
const openPrice = data.openPrice;
6868
const currentPrice = data.currentPrice;
69-
const stopLoss = AbsOpenSpreadFee * 0.6;
69+
const stopLoss = AbsSpreadFee * 0.7;
7070
const holdingStatus = data.holdingStatus;
7171
if (holdingStatus === 'BUY') {
72-
if (openPrice - currentPrice > stopLoss) {
72+
// Info: (20240328 - Jacky) Current Buy price is lower than the open Buy price
73+
if (openPrice - (currentPrice + AbsSpreadFee) > stopLoss) {
7374
return 'CLOSE';
7475
}
7576
}
7677
if (holdingStatus === 'SELL') {
77-
if (currentPrice - openPrice > stopLoss) {
78+
// Info: (20240328 - Jacky) Current Sell price is higher than the open Sell price
79+
if (currentPrice - AbsSpreadFee - openPrice > stopLoss) {
7880
return 'CLOSE';
7981
}
8082
}

src/tradebot/entities/tradebot.entity.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ export class Tradebot {
3636
holdingInstId: string;
3737
positionId: string;
3838
openPrice: number;
39-
absSpreadFee: number;
4039
endAsset: myAsset;
4140
isRunning: boolean;
4241
timer?: NodeJS.Timeout;

src/tradebot/tradebot.service.ts

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import { DewtService } from '../dewt/dewt.service';
55
import { PriceTickerService } from '../price_ticker/price_ticker.service';
66
import { StrategiesService } from '../strategies/strategies.service';
77
import { TransactionService } from '../transaction/transaction.service';
8-
import { QuotationDto } from '../price_ticker/dto/quotation.dto';
98

109
@Injectable()
1110
export class TradebotService {
@@ -135,22 +134,13 @@ export class TradebotService {
135134
' purchase strategy',
136135
);
137136
try {
138-
let quotation: QuotationDto;
139-
if (tradebot.holdingStatus === 'WAIT') {
140-
this.logger.log('Tradebot ' + tradebot.id + ' hasn`t holding position');
141-
quotation = await this.priceTickerService.getCFDQuotation(instId);
142-
} else {
143-
quotation = await this.priceTickerService.getCFDQuotation(
144-
tradebot.holdingStatus,
145-
tradebot.holdingInstId,
146-
);
147-
}
137+
let quotation = await this.priceTickerService.getCFDQuotation(instId);
148138
const priceArray = await this.priceTickerService.getCandlesticks(instId);
149139
const suggestion = await this.strategiesService.getSuggestion(
150140
tradebot.suggestion,
151141
{
152142
priceArray: priceArray,
153-
currentPrice: quotation.data.price,
143+
currentPrice: quotation.data.spotPrice,
154144
spreadFee: quotation.data.spreadFee,
155145
holdingStatus: tradebot.holdingStatus,
156146
},
@@ -159,17 +149,17 @@ export class TradebotService {
159149
tradebot.takeProfit,
160150
{
161151
openPrice: tradebot.openPrice,
162-
currentPrice: quotation.data.price,
163-
spreadFee: tradebot.absSpreadFee,
152+
currentPrice: quotation.data.spotPrice,
153+
spreadFee: quotation.data.spreadFee,
164154
holdingStatus: tradebot.holdingStatus,
165155
},
166156
);
167157
const stopLoss = await this.strategiesService.getStopLoss(
168158
tradebot.stopLoss,
169159
{
170160
openPrice: tradebot.openPrice,
171-
currentPrice: quotation.data.price,
172-
spreadFee: tradebot.absSpreadFee,
161+
currentPrice: quotation.data.spotPrice,
162+
spreadFee: quotation.data.spreadFee,
173163
holdingStatus: tradebot.holdingStatus,
174164
},
175165
);
@@ -191,6 +181,17 @@ export class TradebotService {
191181
'create dewt for tradebot ' + tradebot.id + ' register failed',
192182
);
193183
}
184+
if (tradebot.holdingStatus === 'BUY') {
185+
quotation = await this.priceTickerService.getCFDQuotation(
186+
'SELL',
187+
tradebot.holdingInstId,
188+
);
189+
} else if (tradebot.holdingStatus === 'SELL') {
190+
quotation = await this.priceTickerService.getCFDQuotation(
191+
'BUY',
192+
tradebot.holdingInstId,
193+
);
194+
}
194195
const closeCFDOrderDto =
195196
await this.trancsactionService.closeCFDOrderDTO(
196197
quotation,
@@ -218,7 +219,6 @@ export class TradebotService {
218219
tradebot.updated_at = new Date();
219220
tradebot.positionId = null;
220221
tradebot.openPrice = null;
221-
tradebot.absSpreadFee = null;
222222
tradebot.currentAsset = await this.userService.getMyAsset(
223223
tradebot.dewt,
224224
);
@@ -272,7 +272,6 @@ export class TradebotService {
272272
tradebot.holdingInstId = instId;
273273
tradebot.positionId = createCFDOrder.data.orderSnapshot.id;
274274
tradebot.openPrice = quotation.data.price;
275-
tradebot.absSpreadFee = Math.abs(quotation.data.spreadFee);
276275
tradebot.updated_at = new Date();
277276
tradebot.currentAsset = await this.userService.getMyAsset(
278277
tradebot.dewt,

0 commit comments

Comments
 (0)