Skip to content

Commit

Permalink
feat: adding new flag to trade all possible quantity for buy/sell
Browse files Browse the repository at this point in the history
Signed-off-by: rsercano <[email protected]>
  • Loading branch information
rsercano committed Sep 28, 2020
1 parent 82e16a5 commit fedfa8f
Show file tree
Hide file tree
Showing 8 changed files with 344 additions and 247 deletions.
1 change: 1 addition & 0 deletions docs/api.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 17 additions & 5 deletions lib/cli/placeorder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import { checkDecimalPlaces } from '../utils/utils';
export const placeOrderBuilder = (argv: Argv, side: OrderSide) => {
const command = side === OrderSide.BUY ? 'buy' : 'sell';
argv.positional('quantity', {
type: 'number',
describe: 'the quantity to trade',
type: 'string',
describe: 'the quantity to trade, `all` trades everything',
})
.positional('pair_id', {
type: 'string',
Expand Down Expand Up @@ -39,6 +39,8 @@ export const placeOrderBuilder = (argv: Argv, side: OrderSide) => {
describe: 'immediate-or-cancel',
})
.example(`$0 ${command} 5 LTC/BTC .01 1337`, `place a limit order to ${command} 5 LTC @ 0.01 BTC with local order id 1337`)
.example(`$0 ${command} all LTC/BTC .01`, `place a limit order to ${command} all LTC @ 0.01 BTC`)
.example(`$0 ${command} all BTC/USDT mkt`, `place a market order to ${command} all BTC for USDT`)
.example(`$0 ${command} 3 BTC/USDT mkt`, `place a market order to ${command} 3 BTC for USDT`)
.example(`$0 ${command} 1 BTC/USDT market`, `place a market order to ${command} 1 BTC for USDT`);
};
Expand All @@ -48,9 +50,17 @@ export const placeOrderHandler = async (argv: Arguments<any>, side: OrderSide) =

const numericPrice = Number(argv.price);
const priceStr = argv.price.toLowerCase();
const isAll = argv.quantity === 'all';

const quantity = coinsToSats(argv.quantity);
request.setQuantity(quantity);
if (isAll) {
request.setAll(true);
} else {
if (isNaN(argv.quantity)) {
console.error('quantity is not a valid number');
process.exit(1);
}
request.setQuantity(coinsToSats(parseFloat(argv.quantity)));
}
request.setSide(side);
request.setPairId(argv.pair_id.toUpperCase());
request.setImmediateOrCancel(argv.ioc);
Expand Down Expand Up @@ -81,7 +91,7 @@ export const placeOrderHandler = async (argv: Arguments<any>, side: OrderSide) =
} else {
const subscription = client.placeOrder(request);
let noMatches = true;
let remainingQuantity = quantity;
let remainingQuantity = isAll ? 0 : coinsToSats(parseFloat(argv.quantity));
subscription.on('data', (response: PlaceOrderEvent) => {
if (argv.json) {
console.log(JSON.stringify(response.toObject(), undefined, 2));
Expand Down Expand Up @@ -113,6 +123,8 @@ export const placeOrderHandler = async (argv: Arguments<any>, side: OrderSide) =
subscription.on('end', () => {
if (noMatches) {
console.log('no matches found');
} else if (isAll) {
console.log('no more matches found');
} else if (remainingQuantity > 0) {
console.log(`no more matches found, ${satsToCoinsStr(remainingQuantity)} qty will be discarded`);
}
Expand Down
5 changes: 5 additions & 0 deletions lib/proto/xudrpc.swagger.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions lib/proto/xudrpc_pb.d.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

31 changes: 30 additions & 1 deletion lib/proto/xudrpc_pb.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

40 changes: 36 additions & 4 deletions lib/service/Service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -610,19 +610,21 @@ class Service {
* If price is zero or unspecified a market order will get added.
*/
public placeOrder = async (
args: { pairId: string, price: number, quantity: number, orderId: string, side: number,
replaceOrderId: string, immediateOrCancel: boolean },
args: { pairId: string, price: number, quantity?: number, orderId: string, side: number,
replaceOrderId: string, immediateOrCancel: boolean, all?: boolean },
callback?: (e: ServicePlaceOrderEvent) => void,
) => {
argChecks.PRICE_NON_NEGATIVE(args);
argChecks.PRICE_MAX_DECIMAL_PLACES(args);
argChecks.HAS_PAIR_ID(args);
const { pairId, price, quantity, orderId, side, replaceOrderId, immediateOrCancel } = args;
const { pairId, price, quantity, orderId, side, replaceOrderId, immediateOrCancel, all } = args;

const calculatedQuantity = this.calculateQuantity(all, pairId, price, side, quantity);

const order: OwnMarketOrder | OwnLimitOrder = {
pairId,
price,
quantity,
quantity: calculatedQuantity,
isBuy: side === OrderSide.Buy,
localId: orderId || replaceOrderId,
};
Expand All @@ -648,6 +650,36 @@ class Service {
await this.orderBook.placeMarketOrder(placeOrderRequest);
}

private calculateQuantity(all: boolean | undefined, pairId: string, price: number, side: number, quantity: number | undefined) {
let calculatedQuantity: number;

if (all) {
calculatedQuantity = 0;
this.listOrders({ pairId, owner: Owner.Both, limit: 0, includeAliases: false }).forEach((orderArrays, _) => {
function iterateOrdersAndAddQuantity(orderArray: ServiceOrder[]) {
for (const order of orderArray) {
if (order.quantity) {
if (!price || order.price === price) {
calculatedQuantity += order.quantity;
}
}
}
}

if (side === OrderSide.Buy) {
iterateOrdersAndAddQuantity(orderArrays.sellArray);
} else if (side === OrderSide.Sell) {
iterateOrdersAndAddQuantity(orderArrays.buyArray);
}
});

this.logger.debug(`all flag is true to place order, calculated quantity from orderbook is ${calculatedQuantity}`);
} else {
calculatedQuantity = quantity || 0;
}
return calculatedQuantity;
}

/** Removes a currency. */
public removeCurrency = async (args: { currency: string }) => {
argChecks.VALID_CURRENCY(args);
Expand Down
3 changes: 3 additions & 0 deletions proto/xudrpc.proto
Original file line number Diff line number Diff line change
Expand Up @@ -688,6 +688,9 @@ message PlaceOrderRequest {
string replace_order_id = 6 [json_name = "replace_order_id"];
// Whether the order must be filled immediately and not allowed to enter the order book.
bool immediate_or_cancel = 7 [json_name = "immediate_or_cancel"];
// Whether to trade all available funds.
// If true, the quantity field is ignored.
bool all = 8 [json_name = "all"];
}
message PlaceOrderResponse {
// A list of own orders (or portions thereof) that matched the newly placed order.
Expand Down
Loading

0 comments on commit fedfa8f

Please sign in to comment.