use std::sync::Arc;
use longport::{
blocking::QuoteContextSync,
quote::{RequestCreateWatchlistGroup, RequestUpdateWatchlistGroup},
};
use parking_lot::Mutex;
use pyo3::prelude::*;
use time::PrimitiveDateTime;
use crate::{
config::Config,
error::ErrorNewType,
quote::{
push::handle_push_event,
types::{
AdjustType, CalcIndex, Candlestick, CapitalDistributionResponse, CapitalFlowLine,
FilterWarrantExpiryDate, FilterWarrantInOutBoundsType,
HistoryMarketTemperatureResponse, IntradayLine, IssuerInfo, MarketTemperature,
MarketTradingDays, MarketTradingSession, OptionQuote, ParticipantInfo, Period,
QuotePackageDetail, RealtimeQuote, SecuritiesUpdateMode, Security, SecurityBrokers,
SecurityCalcIndex, SecurityDepth, SecurityListCategory, SecurityQuote,
SecurityStaticInfo, SortOrderType, StrikePriceInfo, SubType, SubTypes, Subscription,
Trade, TradeSessions, WarrantInfo, WarrantQuote, WarrantSortBy, WarrantStatus,
WarrantType, WatchlistGroup,
},
},
time::{PyDateWrapper, PyOffsetDateTimeWrapper},
types::Market,
};
#[derive(Debug, Default)]
pub(crate) struct Callbacks {
pub(crate) quote: Option,
pub(crate) depth: Option,
pub(crate) brokers: Option,
pub(crate) trades: Option,
pub(crate) candlestick: Option,
}
#[pyclass]
pub(crate) struct QuoteContext {
ctx: QuoteContextSync,
callbacks: Arc,
}
#[pymethods]
impl QuoteContext {
#[new]
fn new(config: &Config) -> PyResult {
let callbacks = Arc::new(Mutex::new(Callbacks::default()));
let ctx = QuoteContextSync::try_new(Arc::new(config.0.clone()), {
let callbacks = callbacks.clone();
move |event| {
handle_push_event(&callbacks.lock(), event);
}
})
.map_err(ErrorNewType)?;
Ok(Self { ctx, callbacks })
}
/// Returns the member ID
fn member_id(&self) -> PyResult {
Ok(self.ctx.member_id().map_err(ErrorNewType)?)
}
/// Returns the quote level
fn quote_level(&self) -> PyResult {
Ok(self.ctx.quote_level().map_err(ErrorNewType)?)
}
/// Returns the quote package details
fn quote_package_details(&self) -> PyResult {
self.ctx
.quote_package_details()
.map_err(ErrorNewType)?
.into_iter()
.map(TryInto::try_into)
.collect()
}
/// Set quote callback, after receiving the quote data push, it
/// will call back to this function.
fn set_on_quote(&self, py: Python, callback: PyObject) {
if callback.is_none(py) {
self.callbacks.lock().depth = None;
} else {
self.callbacks.lock().depth = Some(callback);
}
}
/// Set brokers callback, after receiving the brokers data push, it
/// will call back to this function.
fn set_on_brokers(&self, py: Python, callback: PyObject) {
if callback.is_none(py) {
self.callbacks.lock().trades = None;
} else {
self.callbacks.lock().trades = Some(callback);
}
}
/// Set candlestick callback, after receiving the candlestick updated event,
/// it will call back to this function.
fn set_on_candlestick(&self, py: Python