Skip to content

Commit ec5dabe

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 d23e235 commit ec5dabe

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
@@ -757,7 +757,7 @@ static int execute_market_ask_order(bool real, market_t *m, order_t *taker)
757757
return 0;
758758
}
759759

760-
static int execute_market_bid_order(bool real, market_t *m, order_t *taker)
760+
static int execute_market_bid_order(bool real, market_t *m, order_t *taker, bool bid_amount_money)
761761
{
762762
mpd_t *price = mpd_new(&mpd_ctx);
763763
mpd_t *amount = mpd_new(&mpd_ctx);
@@ -775,10 +775,33 @@ static int execute_market_bid_order(bool real, market_t *m, order_t *taker)
775775

776776
order_t *maker = node->value;
777777
mpd_copy(price, maker->price, &mpd_ctx);
778-
if (mpd_cmp(taker->left, maker->left, &mpd_ctx) < 0) {
779-
mpd_copy(amount, taker->left, &mpd_ctx);
778+
779+
if (bid_amount_money) {
780+
mpd_div(amount, taker->left, price, &mpd_ctx);
781+
mpd_rescale(amount, amount, -m->stock_prec, &mpd_ctx);
782+
while (true) {
783+
mpd_mul(result, amount, price, &mpd_ctx);
784+
if (mpd_cmp(result, taker->left, &mpd_ctx) > 0) {
785+
mpd_set_i32(result, -m->stock_prec, &mpd_ctx);
786+
mpd_pow(result, mpd_ten, result, &mpd_ctx);
787+
mpd_sub(amount, amount, result, &mpd_ctx);
788+
} else {
789+
break;
790+
}
791+
}
792+
793+
if (mpd_cmp(amount, maker->left, &mpd_ctx) > 0) {
794+
mpd_copy(amount, maker->left, &mpd_ctx);
795+
}
796+
if (mpd_cmp(amount, mpd_zero, &mpd_ctx) == 0) {
797+
break;
798+
}
780799
} else {
781-
mpd_copy(amount, maker->left, &mpd_ctx);
800+
if (mpd_cmp(taker->left, maker->left, &mpd_ctx) < 0) {
801+
mpd_copy(amount, taker->left, &mpd_ctx);
802+
} else {
803+
mpd_copy(amount, maker->left, &mpd_ctx);
804+
}
782805
}
783806

784807
mpd_mul(deal, price, amount, &mpd_ctx);
@@ -792,7 +815,11 @@ static int execute_market_bid_order(bool real, market_t *m, order_t *taker)
792815
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);
793816
}
794817

795-
mpd_sub(taker->left, taker->left, amount, &mpd_ctx);
818+
if (bid_amount_money) {
819+
mpd_sub(taker->left, taker->left, deal, &mpd_ctx);
820+
} else {
821+
mpd_sub(taker->left, taker->left, amount, &mpd_ctx);
822+
}
796823
mpd_add(taker->deal_stock, taker->deal_stock, amount, &mpd_ctx);
797824
mpd_add(taker->deal_money, taker->deal_money, deal, &mpd_ctx);
798825
mpd_add(taker->deal_fee, taker->deal_fee, bid_fee, &mpd_ctx);
@@ -856,7 +883,7 @@ static int execute_market_bid_order(bool real, market_t *m, order_t *taker)
856883
return 0;
857884
}
858885

859-
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)
886+
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)
860887
{
861888
if (side == MARKET_ORDER_SIDE_ASK) {
862889
// validate user has the balance available to fulfil order
@@ -873,61 +900,92 @@ int market_put_market_order(bool real, json_t **result, market_t *m, uint32_t us
873900
return -3;
874901
}
875902
skiplist_release_iterator(iter);
876-
903+
904+
// validate order amount is at least the minimum order amount
905+
if (mpd_cmp(amount, m->min_amount, &mpd_ctx) < 0) {
906+
return -2;
907+
}
877908
} else {
878-
// calculate money required and number of asks
879-
mpd_t *money_required = mpd_new(&mpd_ctx);
880-
mpd_t *left = mpd_new(&mpd_ctx);
881-
mpd_t *amount_tx = mpd_new(&mpd_ctx);
882-
mpd_t *price = mpd_new(&mpd_ctx);
883-
mpd_t *deal = mpd_new(&mpd_ctx);
884-
mpd_copy(money_required, mpd_zero, &mpd_ctx);
885-
mpd_copy(left, amount, &mpd_ctx);
886-
int ask_count = 0;
887-
skiplist_node *node;
888-
skiplist_iter *iter = skiplist_get_iterator(m->asks);
889-
while ((node = skiplist_next(iter)) != NULL) {
890-
ask_count++;
891-
if (mpd_cmp(left, mpd_zero, &mpd_ctx) == 0) {
892-
break;
909+
if (bid_amount_money) {
910+
// validate user has the balance available to fulfil order
911+
mpd_t *balance = balance_get(user_id, BALANCE_TYPE_AVAILABLE, m->money);
912+
if (!balance || mpd_cmp(balance, amount, &mpd_ctx) < 0) {
913+
return -1;
893914
}
894915

895-
order_t *maker = node->value;
896-
mpd_copy(price, maker->price, &mpd_ctx);
897-
if (mpd_cmp(maker->left, left, &mpd_ctx) < 0) {
898-
mpd_copy(amount_tx, maker->left, &mpd_ctx);
899-
} else {
900-
mpd_copy(amount_tx, left, &mpd_ctx);
916+
// validate there are any market participants on the other side of the order
917+
skiplist_iter *iter = skiplist_get_iterator(m->asks);
918+
skiplist_node *node = skiplist_next(iter);
919+
if (node == NULL) {
920+
skiplist_release_iterator(iter);
921+
return -3;
901922
}
923+
skiplist_release_iterator(iter);
902924

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

914-
// validate user has the balance available to fulfil order
915-
mpd_t *balance = balance_get(user_id, BALANCE_TYPE_AVAILABLE, m->money);
916-
if (!balance || mpd_cmp(balance, money_required, &mpd_ctx) < 0) {
917-
return -1;
918-
}
977+
// validate there are any market participants on the other side of the order
978+
if (ask_count == 0) {
979+
return -3;
980+
}
919981

920-
// validate there are any market participants on the other side of the order
921-
if (ask_count == 0) {
922-
return -3;
982+
// validate order amount is at least the minimum order amount
983+
if (mpd_cmp(amount, m->min_amount, &mpd_ctx) < 0) {
984+
return -2;
985+
}
923986
}
924987
}
925988

926-
// validate order amount is at least the minimum order amount
927-
if (mpd_cmp(amount, m->min_amount, &mpd_ctx) < 0) {
928-
return -2;
929-
}
930-
931989
order_t *order = malloc(sizeof(order_t));
932990
if (order == NULL) {
933991
return -__LINE__;
@@ -965,7 +1023,7 @@ int market_put_market_order(bool real, json_t **result, market_t *m, uint32_t us
9651023
if (side == MARKET_ORDER_SIDE_ASK) {
9661024
ret = execute_market_ask_order(real, m, order);
9671025
} else {
968-
ret = execute_market_bid_order(real, m, order);
1026+
ret = execute_market_bid_order(real, m, order, bid_amount_money);
9691027
}
9701028
if (ret < 0) {
9711029
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)