log taker trade summary (#579)

* add new event for taker trade so arb bots can verify their execution cost without waiting for consume events

Co-authored-by: Nicholas <nicholasgclarke@gmail.com>
This commit is contained in:
Maximilian Schneider 2023-05-13 17:54:27 +02:00 committed by GitHub
parent 08dfb0ddba
commit 9166b761e9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 171 additions and 10 deletions

View File

@ -4,6 +4,8 @@ Update this for each program release and mainnet deployment.
## not on mainnet
- New event: PerpTakerTradeLog immdediatly logs your last trade execution (#579)
## mainnet
### v0.15.0, 2023-5-11

View File

@ -9172,6 +9172,51 @@
}
]
},
{
"name": "PerpTakerTradeLog",
"fields": [
{
"name": "mangoGroup",
"type": "publicKey",
"index": false
},
{
"name": "mangoAccount",
"type": "publicKey",
"index": false
},
{
"name": "perpMarketIndex",
"type": "u16",
"index": false
},
{
"name": "takerSide",
"type": "u8",
"index": false
},
{
"name": "totalBaseLotsTaken",
"type": "i64",
"index": false
},
{
"name": "totalQuoteLotsTaken",
"type": "i64",
"index": false
},
{
"name": "takerFeesPaid",
"type": "i128",
"index": false
},
{
"name": "feePenalty",
"type": "i128",
"index": false
}
]
},
{
"name": "PerpForceClosePositionLog",
"fields": [

View File

@ -397,6 +397,18 @@ pub struct FilledPerpOrderLog {
pub seq_num: u64,
}
#[event]
pub struct PerpTakerTradeLog {
pub mango_group: Pubkey,
pub mango_account: Pubkey,
pub perp_market_index: u16,
pub taker_side: u8,
pub total_base_lots_taken: i64,
pub total_quote_lots_taken: i64, // exclusive fees paid
pub taker_fees_paid: i128, // in native quote units
pub fee_penalty: i128, // in native quote units
}
#[event]
pub struct PerpForceClosePositionLog {
pub mango_group: Pubkey,

View File

@ -1,4 +1,4 @@
use crate::logs::FilledPerpOrderLog;
use crate::logs::{FilledPerpOrderLog, PerpTakerTradeLog};
use crate::state::MangoAccountRefMut;
use crate::{
error::*,
@ -64,9 +64,11 @@ impl<'a> Orderbook<'a> {
let order_id = market.gen_order_id(side, price_data);
// IOC orders have a fee penalty applied regardless of match
if order.needs_penalty_fee() {
apply_penalty(market, mango_account)?;
}
let fee_penalty = if order.needs_penalty_fee() {
apply_penalty(market, mango_account)?
} else {
I80F48::ZERO
};
let perp_position = mango_account.perp_position_mut(market.perp_market_index)?;
@ -165,7 +167,7 @@ impl<'a> Orderbook<'a> {
emit!(FilledPerpOrderLog {
mango_group: market.group.key(),
perp_market_index: market.perp_market_index,
seq_num: seq_num,
seq_num,
});
}
let total_quote_lots_taken = order.max_quote_lots - remaining_quote_lots;
@ -177,7 +179,17 @@ impl<'a> Orderbook<'a> {
// realized when the fill event gets executed
if total_quote_lots_taken > 0 || total_base_lots_taken > 0 {
perp_position.add_taker_trade(side, total_base_lots_taken, total_quote_lots_taken);
apply_fees(market, mango_account, total_quote_lots_taken)?;
let taker_fees_paid = apply_fees(market, mango_account, total_quote_lots_taken)?;
emit!(PerpTakerTradeLog {
mango_group: market.group.key(),
mango_account: *mango_account_pk,
perp_market_index: market.perp_market_index,
taker_side: side as u8,
total_base_lots_taken,
total_quote_lots_taken,
taker_fees_paid: taker_fees_paid.to_bits(),
fee_penalty: fee_penalty.to_bits(),
});
}
// Apply changes to matched asks (handles invalidate on delete!)
@ -365,7 +377,7 @@ fn apply_fees(
market: &mut PerpMarket,
account: &mut MangoAccountRefMut,
quote_lots: i64,
) -> Result<()> {
) -> Result<I80F48> {
let quote_native = I80F48::from_num(market.quote_lot_size * quote_lots);
// The maker fees apply to the maker's account only when the fill event is consumed.
@ -391,11 +403,11 @@ fn apply_fees(
// breaks assumptions.
market.fees_accrued += taker_fees + maker_fees;
Ok(())
Ok(taker_fees)
}
/// Applies a fixed penalty fee to the account, and update the market's fees_accrued
fn apply_penalty(market: &mut PerpMarket, account: &mut MangoAccountRefMut) -> Result<()> {
fn apply_penalty(market: &mut PerpMarket, account: &mut MangoAccountRefMut) -> Result<I80F48> {
let fee_penalty = I80F48::from_num(market.fee_penalty);
account
.fixed
@ -404,5 +416,5 @@ fn apply_penalty(market: &mut PerpMarket, account: &mut MangoAccountRefMut) -> R
let perp_position = account.perp_position_mut(market.perp_market_index)?;
perp_position.record_trading_fee(fee_penalty);
market.fees_accrued += fee_penalty;
Ok(())
Ok(fee_penalty)
}

View File

@ -9172,6 +9172,51 @@ export type MangoV4 = {
}
]
},
{
"name": "PerpTakerTradeLog",
"fields": [
{
"name": "mangoGroup",
"type": "publicKey",
"index": false
},
{
"name": "mangoAccount",
"type": "publicKey",
"index": false
},
{
"name": "perpMarketIndex",
"type": "u16",
"index": false
},
{
"name": "takerSide",
"type": "u8",
"index": false
},
{
"name": "totalBaseLotsTaken",
"type": "i64",
"index": false
},
{
"name": "totalQuoteLotsTaken",
"type": "i64",
"index": false
},
{
"name": "takerFeesPaid",
"type": "i128",
"index": false
},
{
"name": "feePenalty",
"type": "i128",
"index": false
}
]
},
{
"name": "PerpForceClosePositionLog",
"fields": [
@ -18686,6 +18731,51 @@ export const IDL: MangoV4 = {
}
]
},
{
"name": "PerpTakerTradeLog",
"fields": [
{
"name": "mangoGroup",
"type": "publicKey",
"index": false
},
{
"name": "mangoAccount",
"type": "publicKey",
"index": false
},
{
"name": "perpMarketIndex",
"type": "u16",
"index": false
},
{
"name": "takerSide",
"type": "u8",
"index": false
},
{
"name": "totalBaseLotsTaken",
"type": "i64",
"index": false
},
{
"name": "totalQuoteLotsTaken",
"type": "i64",
"index": false
},
{
"name": "takerFeesPaid",
"type": "i128",
"index": false
},
{
"name": "feePenalty",
"type": "i128",
"index": false
}
]
},
{
"name": "PerpForceClosePositionLog",
"fields": [