Skip to content

Commit 16fb4bc

Browse files
committed
logging for orderflow
1 parent 3e3549b commit 16fb4bc

File tree

5 files changed

+180
-130
lines changed

5 files changed

+180
-130
lines changed

src/modules/services.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import { CcxtCandlePrefillService } from './system/ccxt_candle_prefill_service';
2525
import { CcxtCandleWatchService } from './system/ccxt_candle_watch_service';
2626
import { SymbolSearchService } from './system/symbol_search_service';
2727
import { ProfileService } from '../profile/profile_service';
28+
import { ProfileOrderService } from '../profile/profile_order_service';
2829
import { ProfilePairService } from './profile_pair_service';
2930
import { BotRunner } from '../strategy/bot_runner';
3031
import { TechnicalAnalysisValidator } from '../utils/technical_analysis_validator';
@@ -145,6 +146,7 @@ let fileCache: FileCache;
145146
let botRunner: BotRunner;
146147
let exchangeInstanceService: ExchangeInstanceService;
147148
let binancePriceService: BinancePriceService;
149+
let profileOrderService: ProfileOrderService;
148150

149151
const parameters: Parameters = {
150152
projectDir: ''
@@ -201,6 +203,7 @@ export interface Services {
201203
getFileCache(): FileCache;
202204
getBotRunner(): BotRunner;
203205
getBinancePriceService(): BinancePriceService;
206+
getProfileOrderService(): ProfileOrderService;
204207
}
205208

206209
const services: Services = {
@@ -546,7 +549,12 @@ const services: Services = {
546549
return profileService;
547550
}
548551

549-
return (profileService = new ProfileService(this.getSystemUtil(), this.getExchangeInstanceService(), this.getBinancePriceService()));
552+
return (profileService = new ProfileService(
553+
this.getSystemUtil(),
554+
this.getExchangeInstanceService(),
555+
this.getBinancePriceService(),
556+
this.getProfileOrderService()
557+
));
550558
},
551559

552560
getProfilePairService: function (): ProfilePairService {
@@ -621,6 +629,14 @@ const services: Services = {
621629
}
622630

623631
return (binancePriceService = new BinancePriceService(this.getFileCache()));
632+
},
633+
634+
getProfileOrderService: function (): ProfileOrderService {
635+
if (profileOrderService) {
636+
return profileOrderService;
637+
}
638+
639+
return (profileOrderService = new ProfileOrderService(this.getLogger()));
624640
}
625641
};
626642

src/profile/profile_order_service.ts

Lines changed: 109 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import * as ccxt from 'ccxt';
2-
import { MarketData, OrderParams, OrderResult, OrderInfo, OrderSide, PositionInfo } from './types';
2+
import { MarketData, OrderParams, OrderResult, OrderInfo, PositionInfo } from './types';
3+
import { Logger } from '../modules/services';
34

45
/**
56
* Fetches current bid/ask prices for a trading pair
@@ -41,126 +42,132 @@ export function roundAmountDown(value: number, precision: number | undefined): n
4142
}
4243

4344
/**
44-
* Places a limit order on the exchange
45+
* Service for placing orders on exchanges.
46+
* Logger is injected via constructor.
4547
*/
46-
export async function placeLimitOrder(
47-
exchange: ccxt.Exchange,
48-
params: OrderParams
49-
): Promise<OrderResult> {
50-
if (!params.price) {
51-
throw new Error('Price is required for limit orders');
52-
}
48+
export class ProfileOrderService {
49+
constructor(private readonly logger: Logger) {}
50+
51+
/**
52+
* Places a limit order on the exchange
53+
*/
54+
async placeLimitOrder(exchange: ccxt.Exchange, params: OrderParams): Promise<OrderResult> {
55+
if (!params.price) {
56+
throw new Error('Price is required for limit orders');
57+
}
5358

54-
// Load markets for precision info
55-
const markets = await exchange.loadMarkets();
56-
const market = markets[params.pair];
59+
// Load markets for precision info
60+
const markets = await exchange.loadMarkets();
61+
const market = markets[params.pair];
5762

58-
if (!market) {
59-
throw new Error(`Market ${params.pair} not found`);
60-
}
63+
if (!market) {
64+
throw new Error(`Market ${params.pair} not found`);
65+
}
6166

62-
// Calculate base currency amount
63-
let baseAmount: number;
64-
if (params.isQuoteCurrency) {
65-
baseAmount = params.amount / params.price;
66-
} else {
67-
baseAmount = params.amount;
68-
}
67+
// Calculate base currency amount
68+
let baseAmount: number;
69+
if (params.isQuoteCurrency) {
70+
baseAmount = params.amount / params.price;
71+
} else {
72+
baseAmount = params.amount;
73+
}
6974

70-
// Round amount to precision
71-
const roundedBaseAmount = roundAmountDown(baseAmount, market.precision?.amount);
72-
const roundedPrice = roundToPrecision(params.price, market.precision?.price);
75+
// Round amount to precision
76+
const roundedBaseAmount = roundAmountDown(baseAmount, market.precision?.amount);
77+
const roundedPrice = roundToPrecision(params.price, market.precision?.price);
7378

74-
if (!roundedBaseAmount || roundedBaseAmount <= 0) {
75-
const minAmount = market.limits?.amount?.min;
76-
throw new Error(
77-
`Order amount too small for ${params.pair}. Minimum is ${minAmount} ${market.base}` +
78-
(params.isQuoteCurrency ? ` (increase your ${market.quote} amount)` : '')
79+
if (!roundedBaseAmount || roundedBaseAmount <= 0) {
80+
const minAmount = market.limits?.amount?.min;
81+
throw new Error(
82+
`Order amount too small for ${params.pair}. Minimum is ${minAmount} ${market.base}` +
83+
(params.isQuoteCurrency ? ` (increase your ${market.quote} amount)` : '')
84+
);
85+
}
86+
87+
const order = await exchange.createOrder(
88+
params.pair,
89+
'limit',
90+
params.side,
91+
roundedBaseAmount,
92+
roundedPrice
7993
);
80-
}
8194

82-
const order = await exchange.createOrder(
83-
params.pair,
84-
'limit',
85-
params.side,
86-
roundedBaseAmount,
87-
roundedPrice
88-
);
95+
this.logger.info(`Order: ${params.side} ${roundedBaseAmount} ${params.pair} @ ${roundedPrice} (limit)`);
96+
97+
return {
98+
id: order.id,
99+
status: order.status,
100+
type: order.type,
101+
side: order.side,
102+
price: order.price,
103+
amount: order.amount,
104+
filled: order.filled,
105+
remaining: order.remaining,
106+
raw: order
107+
};
108+
}
89109

90-
return {
91-
id: order.id,
92-
status: order.status,
93-
type: order.type,
94-
side: order.side,
95-
price: order.price,
96-
amount: order.amount,
97-
filled: order.filled,
98-
remaining: order.remaining,
99-
raw: order
100-
};
101-
}
110+
/**
111+
* Places a market order on the exchange
112+
* If isQuoteCurrency is true, converts quote amount to base amount first
113+
*/
114+
async placeMarketOrder(exchange: ccxt.Exchange, params: OrderParams): Promise<OrderResult> {
115+
// Load markets for precision info
116+
const markets = await exchange.loadMarkets();
117+
const market = markets[params.pair];
118+
119+
if (!market) {
120+
throw new Error(`Market ${params.pair} not found`);
121+
}
102122

103-
/**
104-
* Places a market order on the exchange
105-
* If isQuoteCurrency is true, converts quote amount to base amount first
106-
*/
107-
export async function placeMarketOrder(
108-
exchange: ccxt.Exchange,
109-
params: OrderParams
110-
): Promise<OrderResult> {
111-
// Load markets for precision info
112-
const markets = await exchange.loadMarkets();
113-
const market = markets[params.pair];
114-
115-
if (!market) {
116-
throw new Error(`Market ${params.pair} not found`);
117-
}
123+
let baseAmount: number;
118124

119-
let baseAmount: number;
125+
if (params.isQuoteCurrency) {
126+
// Convert quote currency amount to base amount using current price
127+
const ticker = await exchange.fetchTicker(params.pair);
128+
const price = ticker.last || ticker.close;
120129

121-
if (params.isQuoteCurrency) {
122-
// Convert quote currency amount to base amount using current price
123-
const ticker = await exchange.fetchTicker(params.pair);
124-
const price = ticker.last || ticker.close;
130+
if (!price) {
131+
throw new Error('Could not fetch current price for market order conversion');
132+
}
125133

126-
if (!price) {
127-
throw new Error('Could not fetch current price for market order conversion');
134+
baseAmount = params.amount / price;
135+
} else {
136+
baseAmount = params.amount;
128137
}
129138

130-
baseAmount = params.amount / price;
131-
} else {
132-
baseAmount = params.amount;
133-
}
139+
// Round amount to precision
140+
const roundedBaseAmount = roundAmountDown(baseAmount, market.precision?.amount);
134141

135-
// Round amount to precision
136-
const roundedBaseAmount = roundAmountDown(baseAmount, market.precision?.amount);
142+
if (!roundedBaseAmount || roundedBaseAmount <= 0) {
143+
const minAmount = market.limits?.amount?.min;
144+
throw new Error(
145+
`Order amount too small for ${params.pair}. Minimum is ${minAmount} ${market.base}` +
146+
(params.isQuoteCurrency ? ` (increase your ${market.quote} amount)` : '')
147+
);
148+
}
137149

138-
if (!roundedBaseAmount || roundedBaseAmount <= 0) {
139-
const minAmount = market.limits?.amount?.min;
140-
throw new Error(
141-
`Order amount too small for ${params.pair}. Minimum is ${minAmount} ${market.base}` +
142-
(params.isQuoteCurrency ? ` (increase your ${market.quote} amount)` : '')
150+
const order = await exchange.createOrder(
151+
params.pair,
152+
'market',
153+
params.side,
154+
roundedBaseAmount
143155
);
144-
}
145-
146-
const order = await exchange.createOrder(
147-
params.pair,
148-
'market',
149-
params.side,
150-
roundedBaseAmount
151-
);
152156

153-
return {
154-
id: order.id,
155-
status: order.status,
156-
type: order.type,
157-
side: order.side,
158-
price: order.price,
159-
amount: order.amount,
160-
filled: order.filled,
161-
remaining: order.remaining,
162-
raw: order
163-
};
157+
this.logger.info(`Order: ${params.side} ${roundedBaseAmount} ${params.pair} @ market`);
158+
159+
return {
160+
id: order.id,
161+
status: order.status,
162+
type: order.type,
163+
side: order.side,
164+
price: order.price,
165+
amount: order.amount,
166+
filled: order.filled,
167+
remaining: order.remaining,
168+
raw: order
169+
};
170+
}
164171
}
165172

166173
/**

src/profile/profile_service.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@ import { ExchangeInstanceService } from '../modules/system/exchange_instance_ser
55
import { BinancePriceService } from '../utils/binance_price_service';
66
import {
77
fetchMarketData,
8-
placeLimitOrder,
9-
placeMarketOrder,
8+
ProfileOrderService,
109
fetchOpenOrders as fetchOpenOrdersCCXT,
1110
fetchClosedOrders as fetchClosedOrdersCCXT,
1211
cancelOrder as cancelOrderCCXT,
@@ -20,6 +19,7 @@ export class ProfileService {
2019
private configService: ConfigService,
2120
private exchangeInstanceService: ExchangeInstanceService,
2221
private binancePriceService: BinancePriceService,
22+
private orderService: ProfileOrderService
2323
) {}
2424

2525
private generateId(): string {
@@ -192,9 +192,9 @@ export class ProfileService {
192192
const exchange = await this.getExchangeForProfile(profileId);
193193

194194
if (params.type === 'market') {
195-
return placeMarketOrder(exchange, params);
195+
return this.orderService.placeMarketOrder(exchange, params);
196196
} else {
197-
return placeLimitOrder(exchange, params);
197+
return this.orderService.placeLimitOrder(exchange, params);
198198
}
199199
}
200200

src/strategy/bot_runner.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,15 +83,15 @@ export class BotRunner {
8383

8484
if (minutesSinceEpoch % periodMin !== 0) continue;
8585

86-
this.logger.info(`BotRunner: triggering "${bot.name}" (${bot.strategy} ${profile.exchange}:${bot.pair} ${bot.interval})`);
86+
this.logger.debug(`BotRunner: triggering "${bot.name}" (${bot.strategy} ${profile.exchange}:${bot.pair} ${bot.interval})`);
8787

8888
try {
8989
await this.runBot(bot, profile);
9090
} catch (err) {
9191
this.logger.error(`BotRunner: bot "${bot.name}" (${bot.strategy} ${profile.exchange}:${bot.pair}) failed: ${err}`);
9292
}
9393

94-
this.logger.info(`BotRunner: triggered "${bot.name}" (${bot.strategy} ${profile.exchange}:${bot.pair} ${bot.interval})`);
94+
this.logger.debug(`BotRunner: triggered "${bot.name}" (${bot.strategy} ${profile.exchange}:${bot.pair} ${bot.interval})`);
9595
}
9696
}
9797

0 commit comments

Comments
 (0)