wisespace-io / binance-rs

Rust Library for the Binance API
Other
649 stars 295 forks source link

Get better informations return by market buy request #45

Closed clementpl closed 4 years ago

clementpl commented 4 years ago

Hello,

I'm actually using the market_buy/market_sell api for a trading bot. But the return of those function is not very helpfull. I first get a transaction object (after "market_buy"). With this transaction object i can then make a request "order_status" but unfortunately the return of order status don't give me info about the price or commission.

Here is the actual return of market_buy (transaction) and order_status (order)

RETURN MARKET_BUY
Transaction { symbol: "BTCUSDT", order_id: ..an_id_here.., client_order_id: "..an_id_here..",
transact_time: 1588629578067 }

RETURN ORDER STATUS
Order { symbol: "BTCUSDT", order_id: ..an_id_here.., client_order_id: "..an_id_here..",
price: 0.0, orig_qty: "0.00219300", executed_qty: "0.00219300", status: "FILLED",
time_in_force: "GTC", type_name: "MARKET", side: "BUY", stop_price: 0.0,
iceberg_qty: "0.00000000", time: 1588629578067 }

As we can see the price is equal to 0 in the return of order status. Maybe there is another request to use to get more usefull information about the order but i didn't find which request.

I manage to look at the data fetch before the deserialization to see where I can get more information Here is the raw data fetch before deserialization

RAW DATA AFTER MARKET BUY (before deserialization):
 "{\"symbol\":\"BTCUSDT\",\"orderId\":..an_id_here..,\"orderListId\":..an_id_here..,
\"clientOrderId\":\"..an_id_here..\",\"transactTime\":1588629578067,
\"price\":\"0.00000000\",\"origQty\":\"0.00219300\",\"executedQty\":\"0.00219300\",
\"cummulativeQuoteQty\":\"19.59425763\",\"status\":\"FILLED\",\"timeInForce\":\"GTC\",
\"type\":\"MARKET\",\"side\":\"BUY\",
\"fills\":[{\"price\":\"8934.91000000\",\"qty\":\"0.00219300\",\"commission\":\"0.00086106\",\"commissionAsset\":\"BNB\",\"tradeId\":309149253}]}"

RAW DATA AFTER ORDER STATUS (before deserialization):
"{\"symbol\":\"BTCUSDT\",\"orderId\":..an_id_here..,\"orderListId\":-1,
\"clientOrderId\":\"..an_id_here..\",\"price\":\"0.00000000\",\"origQty\":\"0.00219300\",
\"executedQty\":\"0.00219300\",\"cummulativeQuoteQty\":\"19.59425763\",
\"status\":\"FILLED\",\"timeInForce\":\"GTC\",\"type\":\"MARKET\",\"side\":\"BUY\",
\"stopPrice\":\"0.00000000\",\"icebergQty\":\"0.00000000\",\"time\":1588629578067,
\"updateTime\":1588629578067,\"isWorking\":true,\"origQuoteOrderQty\":\"0.00000000\"}"

We can see that the "raw data" fetch after the market buy request have usefull information which are not parsed. It could be very usefull to get the "fills" property to let the user calculate the average price + sum of comission.

I don't know how it can be done because I know it's not possible to get the same kind of return with the limit_order request (not directly executed).

Maybe the market_buy request could return an Order directly and we can add the "fills property" in an Option so it doesn't affect the return of order_status.

clementpl commented 4 years ago

After testing the solution with an Option property fills. I can tell you the solution is not working because there is many different field time is now transact_time, there is no stop price, ... So in local I made a 2 new struct

#[derive(Debug, Serialize, Deserialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct MarketOrder {
    pub symbol: String,
    pub order_id: u64,
    pub order_list_id: i64,
    pub client_order_id: String,
    pub transact_time: u64,
    pub price: String,
    pub orig_qty: String,
    pub executed_qty: String,
    pub cummulative_quote_qty: String,
    pub status: String,
    pub time_in_force: String,
    pub side: String,
    pub fills: Vec<FillInfo>,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct FillInfo {
    pub price: String,
    pub qty: String,
    pub commission: String,
    pub commission_asset: String,
    pub tradeId: u64,
}

And i made the market_buy and market_sell return a MarketOrder

    pub fn market_buy<S, F>(&self, symbol: S, qty: F) -> Result<MarketOrder>
    pub fn market_sell<S, F>(&self, symbol: S, qty: F) -> Result<MarketOrder>

For me it's enough, I can get all the information I need. I don't know how you want to do for the library.

mpskowron commented 4 years ago

I've done similar thing in my fork of binance-async-rs (https://github.com/mpskowron/binance-async-rs/commit/00777b54aca51a9f1ac4a807606f13066309e1c3) - I'll probably submit a pull request to async version of this library this week. Would be great if this and async version merged. MarketOrder is not a correct name here - according to binance docs (https://github.com/binance-exchange/binance-official-api-docs/blob/master/rest-api.md) this is the Full order response type which is also returned by default for limit orders.

wisespace-io commented 4 years ago

@clementpl I think your solution would suit well for other as well. But as @mpskowron said, you can add the fields to Transaction structure.

pub struct Transaction {
    pub symbol: String,
    pub order_id: u64,
    pub client_order_id: String,
    pub transact_time: u64,
    #[serde(with = "string_or_float")]
    pub price: f64,
    pub orig_qty: String,
    pub executed_qty: String,
    pub cummulative_quote_qty: String,
    pub status: String,
    pub time_in_force: String,
    pub side: String,
    pub fills: Vec<FillInfo>,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct FillInfo {
    #[serde(with = "string_or_float")]
    pub price: f64,
    pub qty: String,
    pub commission: String,
    pub commission_asset: String,
    pub tradeId: u64,
}

You can submite a Pull Request otherwise I can update myself.

@mpskowron I am going to add async support to this library as soon as the Future API is implemented, see the open Pull Request.

wisespace-io commented 4 years ago

@clementpl just to let you know that after merging I realized that some fields should be f64, such as commision, so I updated them

clementpl commented 4 years ago

Yes thanks to the rust compiler I saw that haha :) Thank you