Skip to content

Commit 54531bd

Browse files
committed
added extra optional parameter "bid_amount_money" to "order.put_market_stock" RPC.
Default value is true and has no change to behavior. If the value is false then the "amount" parameter of a market bid is treated as "stock" instead of "money"
1 parent 86edfec commit 54531bd

3 files changed

Lines changed: 122 additions & 55 deletions

File tree

matchengine/me_market.c

Lines changed: 110 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -751,7 +751,7 @@ static int execute_market_ask_order(bool real, market_t *m, order_t *taker)
751751
return 0;
752752
}
753753

754-
static int execute_market_bid_order(bool real, market_t *m, order_t *taker)
754+
static int execute_market_bid_order(bool real, market_t *m, order_t *taker, bool bid_amount_money)
755755
{
756756
mpd_t *price = mpd_new(&mpd_ctx);
757757
mpd_t *amount = mpd_new(&mpd_ctx);
@@ -769,10 +769,33 @@ static int execute_market_bid_order(bool real, market_t *m, order_t *taker)
769769

770770
order_t *maker = node->value;
771771
mpd_copy(price, maker->price, &mpd_ctx);
772-
if (mpd_cmp(taker->left, maker->left, &mpd_ctx) < 0) {
773-
mpd_copy(amount, taker->left, &mpd_ctx);
772+
773+
if (bid_amount_money) {
774+
mpd_div(amount, taker->left, price, &mpd_ctx);
775+
mpd_rescale(amount, amount, -m->stock_prec, &mpd_ctx);
776+
while (true) {
777+
mpd_mul(result, amount, price, &mpd_ctx);
778+
if (mpd_cmp(result, taker->left, &mpd_ctx) > 0) {
779+
mpd_set_i32(result, -m->stock_prec, &mpd_ctx);
780+
mpd_pow(result, mpd_ten, result, &mpd_ctx);
781+
mpd_sub(amount, amount, result, &mpd_ctx);
782+
} else {
783+
break;
784+
}
785+
}
786+
787+
if (mpd_cmp(amount, maker->left, &mpd_ctx) > 0) {
788+
mpd_copy(amount, maker->left, &mpd_ctx);
789+
}
790+
if (mpd_cmp(amount, mpd_zero, &mpd_ctx) == 0) {
791+
break;
792+
}
774793
} else {
775-
mpd_copy(amount, maker->left, &mpd_ctx);
794+
if (mpd_cmp(taker->left, maker->left, &mpd_ctx) < 0) {
795+
mpd_copy(amount, taker->left, &mpd_ctx);
796+
} else {
797+
mpd_copy(amount, maker->left, &mpd_ctx);
798+
}
776799
}
777800

778801
mpd_mul(deal, price, amount, &mpd_ctx);
@@ -786,7 +809,11 @@ static int execute_market_bid_order(bool real, market_t *m, order_t *taker)
786809
push_deal_message(taker->update_time, m->name, maker, taker, price, amount, ask_fee, bid_fee, MARKET_ORDER_SIDE_BID, deal_id, m->stock, m->money);
787810
}
788811

789-
mpd_sub(taker->left, taker->left, amount, &mpd_ctx);
812+
if (bid_amount_money) {
813+
mpd_sub(taker->left, taker->left, deal, &mpd_ctx);
814+
} else {
815+
mpd_sub(taker->left, taker->left, amount, &mpd_ctx);
816+
}
790817
mpd_add(taker->deal_stock, taker->deal_stock, amount, &mpd_ctx);
791818
mpd_add(taker->deal_money, taker->deal_money, deal, &mpd_ctx);
792819
mpd_add(taker->deal_fee, taker->deal_fee, bid_fee, &mpd_ctx);
@@ -850,7 +877,7 @@ static int execute_market_bid_order(bool real, market_t *m, order_t *taker)
850877
return 0;
851878
}
852879

853-
int market_put_market_order(bool real, json_t **result, market_t *m, uint32_t user_id, uint32_t side, mpd_t *amount, mpd_t *taker_fee, const char *source)
880+
int market_put_market_order(bool real, json_t **result, market_t *m, uint32_t user_id, uint32_t side, mpd_t *amount, mpd_t *taker_fee, const char *source, bool bid_amount_money)
854881
{
855882
if (side == MARKET_ORDER_SIDE_ASK) {
856883
// validate user has the balance available to fulfil order
@@ -867,61 +894,92 @@ int market_put_market_order(bool real, json_t **result, market_t *m, uint32_t us
867894
return -3;
868895
}
869896
skiplist_release_iterator(iter);
870-
897+
898+
// validate order amount is at least the minimum order amount
899+
if (mpd_cmp(amount, m->min_amount, &mpd_ctx) < 0) {
900+
return -2;
901+
}
871902
} else {
872-
// calculate money required and number of asks
873-
mpd_t *money_required = mpd_new(&mpd_ctx);
874-
mpd_t *left = mpd_new(&mpd_ctx);
875-
mpd_t *amount_tx = mpd_new(&mpd_ctx);
876-
mpd_t *price = mpd_new(&mpd_ctx);
877-
mpd_t *deal = mpd_new(&mpd_ctx);
878-
mpd_copy(money_required, mpd_zero, &mpd_ctx);
879-
mpd_copy(left, amount, &mpd_ctx);
880-
int ask_count = 0;
881-
skiplist_node *node;
882-
skiplist_iter *iter = skiplist_get_iterator(m->asks);
883-
while ((node = skiplist_next(iter)) != NULL) {
884-
ask_count++;
885-
if (mpd_cmp(left, mpd_zero, &mpd_ctx) == 0) {
886-
break;
903+
if (bid_amount_money) {
904+
// validate user has the balance available to fulfil order
905+
mpd_t *balance = balance_get(user_id, BALANCE_TYPE_AVAILABLE, m->money);
906+
if (!balance || mpd_cmp(balance, amount, &mpd_ctx) < 0) {
907+
return -1;
887908
}
888909

889-
order_t *maker = node->value;
890-
mpd_copy(price, maker->price, &mpd_ctx);
891-
if (mpd_cmp(maker->left, left, &mpd_ctx) < 0) {
892-
mpd_copy(amount_tx, maker->left, &mpd_ctx);
893-
} else {
894-
mpd_copy(amount_tx, left, &mpd_ctx);
910+
// validate there are any market participants on the other side of the order
911+
skiplist_iter *iter = skiplist_get_iterator(m->asks);
912+
skiplist_node *node = skiplist_next(iter);
913+
if (node == NULL) {
914+
skiplist_release_iterator(iter);
915+
return -3;
895916
}
917+
skiplist_release_iterator(iter);
896918

897-
mpd_mul(deal, price, amount_tx, &mpd_ctx);
898-
mpd_sub(left, left, amount_tx, &mpd_ctx);
899-
mpd_add(money_required, money_required, deal, &mpd_ctx);
900-
}
901-
skiplist_release_iterator(iter);
902-
mpd_del(money_required);
903-
mpd_del(left);
904-
mpd_del(amount_tx);
905-
mpd_del(price);
906-
mpd_del(deal);
919+
// validate order amount is at least the minimum order amount
920+
order_t *order = node->value;
921+
mpd_t *require = mpd_new(&mpd_ctx);
922+
mpd_mul(require, order->price, m->min_amount, &mpd_ctx);
923+
if (mpd_cmp(amount, require, &mpd_ctx) < 0) {
924+
mpd_del(require);
925+
return -2;
926+
}
927+
mpd_del(require);
928+
} else {
929+
// calculate money required and number of asks
930+
mpd_t *money_required = mpd_new(&mpd_ctx);
931+
mpd_t *left = mpd_new(&mpd_ctx);
932+
mpd_t *amount_tx = mpd_new(&mpd_ctx);
933+
mpd_t *price = mpd_new(&mpd_ctx);
934+
mpd_t *deal = mpd_new(&mpd_ctx);
935+
mpd_copy(money_required, mpd_zero, &mpd_ctx);
936+
mpd_copy(left, amount, &mpd_ctx);
937+
int ask_count = 0;
938+
skiplist_node *node;
939+
skiplist_iter *iter = skiplist_get_iterator(m->asks);
940+
while ((node = skiplist_next(iter)) != NULL) {
941+
ask_count++;
942+
if (mpd_cmp(left, mpd_zero, &mpd_ctx) == 0) {
943+
break;
944+
}
945+
946+
order_t *maker = node->value;
947+
mpd_copy(price, maker->price, &mpd_ctx);
948+
if (mpd_cmp(maker->left, left, &mpd_ctx) < 0) {
949+
mpd_copy(amount_tx, maker->left, &mpd_ctx);
950+
} else {
951+
mpd_copy(amount_tx, left, &mpd_ctx);
952+
}
953+
954+
mpd_mul(deal, price, amount_tx, &mpd_ctx);
955+
mpd_sub(left, left, amount_tx, &mpd_ctx);
956+
mpd_add(money_required, money_required, deal, &mpd_ctx);
957+
}
958+
skiplist_release_iterator(iter);
959+
mpd_del(money_required);
960+
mpd_del(left);
961+
mpd_del(amount_tx);
962+
mpd_del(price);
963+
mpd_del(deal);
964+
965+
// validate user has the balance available to fulfil order
966+
mpd_t *balance = balance_get(user_id, BALANCE_TYPE_AVAILABLE, m->money);
967+
if (!balance || mpd_cmp(balance, money_required, &mpd_ctx) < 0) {
968+
return -1;
969+
}
907970

908-
// validate user has the balance available to fulfil order
909-
mpd_t *balance = balance_get(user_id, BALANCE_TYPE_AVAILABLE, m->money);
910-
if (!balance || mpd_cmp(balance, money_required, &mpd_ctx) < 0) {
911-
return -1;
912-
}
971+
// validate there are any market participants on the other side of the order
972+
if (ask_count == 0) {
973+
return -3;
974+
}
913975

914-
// validate there are any market participants on the other side of the order
915-
if (ask_count == 0) {
916-
return -3;
976+
// validate order amount is at least the minimum order amount
977+
if (mpd_cmp(amount, m->min_amount, &mpd_ctx) < 0) {
978+
return -2;
979+
}
917980
}
918981
}
919982

920-
// validate order amount is at least the minimum order amount
921-
if (mpd_cmp(amount, m->min_amount, &mpd_ctx) < 0) {
922-
return -2;
923-
}
924-
925983
order_t *order = malloc(sizeof(order_t));
926984
if (order == NULL) {
927985
return -__LINE__;
@@ -959,7 +1017,7 @@ int market_put_market_order(bool real, json_t **result, market_t *m, uint32_t us
9591017
if (side == MARKET_ORDER_SIDE_ASK) {
9601018
ret = execute_market_ask_order(real, m, order);
9611019
} else {
962-
ret = execute_market_bid_order(real, m, order);
1020+
ret = execute_market_bid_order(real, m, order, bid_amount_money);
9631021
}
9641022
if (ret < 0) {
9651023
log_error("execute order: %"PRIu64" fail: %d", order->id, ret);

matchengine/me_market.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ market_t *market_create(struct market *conf);
5252
int market_get_status(market_t *m, size_t *ask_count, mpd_t *ask_amount, size_t *bid_count, mpd_t *bid_amount);
5353

5454
int market_put_limit_order(bool real, json_t **result, market_t *m, uint32_t user_id, uint32_t side, mpd_t *amount, mpd_t *price, mpd_t *taker_fee, mpd_t *maker_fee, const char *source);
55-
int market_put_market_order(bool real, json_t **result, market_t *m, uint32_t user_id, uint32_t side, mpd_t *amount, mpd_t *taker_fee, const char *source);
55+
int market_put_market_order(bool real, json_t **result, market_t *m, uint32_t user_id, uint32_t side, mpd_t *amount, mpd_t *taker_fee, const char *source, bool bid_amount_money);
5656
int market_cancel_order(bool real, json_t **result, market_t *m, order_t *order);
5757

5858
int market_put_order(market_t *m, order_t *order);

matchengine/me_server.c

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -457,7 +457,7 @@ static int on_cmd_order_put_limit(nw_ses *ses, rpc_pkg *pkg, json_t *params)
457457

458458
static int on_cmd_order_put_market(nw_ses *ses, rpc_pkg *pkg, json_t *params)
459459
{
460-
if (json_array_size(params) != 6)
460+
if (json_array_size(params) != 6 && json_array_size(params) != 7)
461461
return reply_error_invalid_argument(ses, pkg);
462462

463463
// user_id
@@ -504,8 +504,17 @@ static int on_cmd_order_put_market(nw_ses *ses, rpc_pkg *pkg, json_t *params)
504504
if (strlen(source) >= SOURCE_MAX_LEN)
505505
goto invalid_argument;
506506

507+
// bid amount money (should the bid amount be treated as "money" or "stock")
508+
// optional parameter, default is true
509+
bool bid_amount_money = true;
510+
if (json_array_size(params) == 7) {
511+
if (!json_is_boolean(json_array_get(params, 6)))
512+
goto invalid_argument;
513+
bid_amount_money = json_boolean_value(json_array_get(params, 6));
514+
}
515+
507516
json_t *result = NULL;
508-
int ret = market_put_market_order(true, &result, market, user_id, side, amount, taker_fee, source);
517+
int ret = market_put_market_order(true, &result, market, user_id, side, amount, taker_fee, source, bid_amount_money);
509518

510519
mpd_del(amount);
511520
mpd_del(taker_fee);

0 commit comments

Comments
 (0)