use std::sync::Arc;
use std::time::Duration;
use quickfix_tokio::fix44::messages::new_order_single::NewOrderSingle;
use quickfix_tokio::fix44::{AnyMessage, classify, fields};
use quickfix_tokio::{
Engine, MemoryStoreFactory, SessionEvent, Settings, TracingLogFactory, UtcTimestamp,
dec, event_channel,
};
#[tokio::main]
async fn main() -> quickfix_tokio::Result<()> {
tracing_subscriber::fmt().with_max_level(tracing::Level::INFO).init();
let settings = Settings::parse(
"[SESSION]\n\
ConnectionType=initiator\n\
BeginString=FIX.4.4\n\
SenderCompID=CLIENT\n\
TargetCompID=EXECUTOR\n\
SocketConnectHost=127.0.0.1\n\
SocketConnectPort=9876\n\
HeartBtInt=30\n\
ReconnectInterval=2\n\
DataDictionary=spec/FIX44.xml\n",
)?;
let (app, mut events) = event_channel();
let engine = Engine::start(
&settings,
Arc::new(app),
Arc::new(MemoryStoreFactory::new()),
Arc::new(TracingLogFactory),
)
.await?;
let session = engine.session("FIX.4.4", "CLIENT", "EXECUTOR").unwrap();
let mut ticker = tokio::time::interval(Duration::from_secs(1));
const CAP: u64 = 3;
let mut sent = 0u64;
let mut filled = 0u64;
loop {
tokio::select! {
maybe = events.recv() => {
let Some(event) = maybe else { break }; match event {
SessionEvent::LoggedOn(id) => println!("logged on: {id}"),
SessionEvent::LoggedOut(_) => break,
SessionEvent::App(msg, _) => {
if let AnyMessage::ExecutionReport(er) = classify(msg) {
filled += 1;
println!(
"fill #{filled}: {} {} x {} @ {} ({})",
er.cl_ord_id().unwrap_or_default(),
er.cum_qty().unwrap_or(dec!(0)),
er.symbol().unwrap_or_default(),
er.avg_px().unwrap_or(dec!(0)),
er.ord_status().map(|c| c.to_string()).unwrap_or_default(),
);
if filled >= CAP {
break;
}
}
}
_ => {}
}
}
_ = ticker.tick() => {
if sent < CAP && session.is_logged_on().await {
sent += 1;
let mut order = NewOrderSingle::new(
format!("ORDER-{sent}"),
fields::Side::BUY,
UtcTimestamp::now(),
fields::OrdType::LIMIT,
);
order.set_symbol("TSLA");
order.set_order_qty(dec!(100));
order.set_price(dec!(101.25));
session.send(order.into()).await?;
println!("sent ORDER-{sent}");
}
}
}
}
session.logout().await?;
tokio::time::sleep(Duration::from_millis(500)).await;
engine.stop().await;
Ok(())
}