mirror of
https://github.com/exchanges-lab/tradesync.git
synced 2026-08-08 14:24:42 +08:00
feat: enhance HyperliquidMonitor to parse and emit all trade actions: Open, Increase, Decrease, Close
This commit is contained in:
+11
-3
@@ -28,11 +28,19 @@ async fn main() -> Result<()> {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
info!("Listening for position open events. Close with Ctrl+C...");
|
info!("Listening for position trade events. Close with Ctrl+C...");
|
||||||
while let Some(event) = rx.recv().await {
|
while let Some(event) = rx.recv().await {
|
||||||
info!(
|
info!(
|
||||||
"DEMO RECEIVED POSITION OPEN: coin={}, side={}, px={}, sz={}, time={}, tid={}",
|
"DEMO RECEIVED POSITION TRADE: coin={}, side={}, px={}, sz={}, action={:?}, start_pos={}, end_pos={}, time={}, tid={}",
|
||||||
event.coin, event.side, event.px, event.sz, event.time, event.tid
|
event.coin,
|
||||||
|
event.side,
|
||||||
|
event.px,
|
||||||
|
event.sz,
|
||||||
|
event.action,
|
||||||
|
event.start_pos,
|
||||||
|
event.end_pos,
|
||||||
|
event.time,
|
||||||
|
event.tid
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+32
-14
@@ -1,4 +1,4 @@
|
|||||||
use crate::structs::PositionOpenEvent;
|
use crate::structs::{PositionTradeEvent, TradeAction};
|
||||||
use alloy::primitives::Address;
|
use alloy::primitives::Address;
|
||||||
use hyperliquid_rust_sdk::{BaseUrl, InfoClient, Message, Subscription, UserData};
|
use hyperliquid_rust_sdk::{BaseUrl, InfoClient, Message, Subscription, UserData};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
@@ -31,7 +31,7 @@ impl HyperliquidMonitor {
|
|||||||
/// Runs the monitor WebSocket subscription in a loop, reconnecting if disconnected.
|
/// Runs the monitor WebSocket subscription in a loop, reconnecting if disconnected.
|
||||||
pub async fn run(
|
pub async fn run(
|
||||||
&self,
|
&self,
|
||||||
event_tx: UnboundedSender<PositionOpenEvent>,
|
event_tx: UnboundedSender<PositionTradeEvent>,
|
||||||
) -> Result<(), HyperliquidMonitorError> {
|
) -> Result<(), HyperliquidMonitorError> {
|
||||||
let base_url = if self.is_testnet {
|
let base_url = if self.is_testnet {
|
||||||
BaseUrl::Testnet
|
BaseUrl::Testnet
|
||||||
@@ -90,36 +90,54 @@ impl HyperliquidMonitor {
|
|||||||
debug!(user_msg = ?user_msg, "Received user event message");
|
debug!(user_msg = ?user_msg, "Received user event message");
|
||||||
if let UserData::Fills(fills) = user_msg.data {
|
if let UserData::Fills(fills) = user_msg.data {
|
||||||
for fill in fills {
|
for fill in fills {
|
||||||
// Check if start_position is 0, which indicates a new position is opening
|
// Parse position details
|
||||||
let start_pos: f64 = fill.start_position.parse().unwrap_or(0.0);
|
let start_pos: f64 = fill.start_position.parse().unwrap_or(0.0);
|
||||||
if start_pos == 0.0 {
|
let sz: f64 = fill.sz.parse().unwrap_or(0.0);
|
||||||
|
let dir = if fill.side == "B" { 1.0 } else { -1.0 };
|
||||||
|
let change = dir * sz;
|
||||||
|
let end_pos = start_pos + change;
|
||||||
|
|
||||||
|
// Determine the trade action
|
||||||
|
let action = if start_pos == 0.0 {
|
||||||
|
TradeAction::Open
|
||||||
|
} else if end_pos == 0.0 {
|
||||||
|
TradeAction::Close
|
||||||
|
} else if start_pos.signum() != end_pos.signum() {
|
||||||
|
TradeAction::Decrease
|
||||||
|
} else if end_pos.abs() > start_pos.abs() {
|
||||||
|
TradeAction::Increase
|
||||||
|
} else {
|
||||||
|
TradeAction::Decrease
|
||||||
|
};
|
||||||
|
|
||||||
info!(
|
info!(
|
||||||
coin = %fill.coin,
|
coin = %fill.coin,
|
||||||
side = %fill.side,
|
side = %fill.side,
|
||||||
px = %fill.px,
|
px = %fill.px,
|
||||||
sz = %fill.sz,
|
sz = %fill.sz,
|
||||||
|
action = ?action,
|
||||||
|
start_pos = start_pos,
|
||||||
|
end_pos = end_pos,
|
||||||
tid = fill.tid,
|
tid = fill.tid,
|
||||||
"Position opening detected!"
|
"Wallet trade fill detected!"
|
||||||
);
|
);
|
||||||
let event = PositionOpenEvent {
|
|
||||||
|
let event = PositionTradeEvent {
|
||||||
coin: fill.coin,
|
coin: fill.coin,
|
||||||
side: fill.side,
|
side: fill.side,
|
||||||
px: fill.px,
|
px: fill.px,
|
||||||
sz: fill.sz,
|
sz: fill.sz,
|
||||||
time: fill.time,
|
time: fill.time,
|
||||||
tid: fill.tid,
|
tid: fill.tid,
|
||||||
|
action,
|
||||||
|
start_pos: fill.start_position.clone(),
|
||||||
|
end_pos: format!("{:.5}", end_pos),
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Err(e) = event_tx.send(event) {
|
if let Err(e) = event_tx.send(event) {
|
||||||
error!(
|
error!(
|
||||||
error = ?e,
|
error = ?e,
|
||||||
"Failed to send PositionOpenEvent through channel"
|
"Failed to send PositionTradeEvent through channel"
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
debug!(
|
|
||||||
coin = %fill.coin,
|
|
||||||
start_pos = start_pos,
|
|
||||||
"Ignore non-opening trade fill"
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -2,4 +2,4 @@ pub mod hyperliquid;
|
|||||||
pub mod structs;
|
pub mod structs;
|
||||||
|
|
||||||
pub use hyperliquid::{HyperliquidMonitor, HyperliquidMonitorError};
|
pub use hyperliquid::{HyperliquidMonitor, HyperliquidMonitorError};
|
||||||
pub use structs::PositionOpenEvent;
|
pub use structs::{PositionTradeEvent, TradeAction};
|
||||||
|
|||||||
+4
-1
@@ -48,9 +48,12 @@ async fn main() -> Result<()> {
|
|||||||
side = %event.side,
|
side = %event.side,
|
||||||
px = %event.px,
|
px = %event.px,
|
||||||
sz = %event.sz,
|
sz = %event.sz,
|
||||||
|
action = ?event.action,
|
||||||
|
start_pos = %event.start_pos,
|
||||||
|
end_pos = %event.end_pos,
|
||||||
time = event.time,
|
time = event.time,
|
||||||
tid = event.tid,
|
tid = event.tid,
|
||||||
"Captured position opening event!"
|
"Captured position trade event!"
|
||||||
);
|
);
|
||||||
// Notion database integration will be wired here in the future
|
// Notion database integration will be wired here in the future
|
||||||
}
|
}
|
||||||
|
|||||||
+20
-4
@@ -1,10 +1,26 @@
|
|||||||
/// Represents a detected position opening event on Hyperliquid.
|
/// The action type of a trade fill relative to the position.
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub enum TradeAction {
|
||||||
|
/// Opening a position (initial position size was 0)
|
||||||
|
Open,
|
||||||
|
/// Adding to an existing position (absolute position size increases)
|
||||||
|
Increase,
|
||||||
|
/// Reducing an existing position (absolute position size decreases but remains non-zero)
|
||||||
|
Decrease,
|
||||||
|
/// Fully closing an existing position (resulting position size becomes 0)
|
||||||
|
Close,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Represents a detected trade event on Hyperliquid affecting a wallet's position.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct PositionOpenEvent {
|
pub struct PositionTradeEvent {
|
||||||
pub coin: String,
|
pub coin: String,
|
||||||
pub side: String, // "B" (Buy) or "S" (Sell)
|
pub side: String, // "B" (Buy) or "S" (Sell)
|
||||||
pub px: String, // Price as string
|
pub px: String, // Price as string
|
||||||
pub sz: String, // Size as string
|
pub sz: String, // Trade size as string
|
||||||
pub time: u64, // Epoch timestamp in milliseconds
|
pub time: u64, // Epoch timestamp in milliseconds
|
||||||
pub tid: u64, // Unique trade/fill ID
|
pub tid: u64, // Unique trade ID
|
||||||
|
pub action: TradeAction,
|
||||||
|
pub start_pos: String, // Position size before the trade
|
||||||
|
pub end_pos: String, // Position size after the trade
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user