Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
Signed-off-by: Pushkar Mishra <[email protected]>
  • Loading branch information
Pushkarm029 committed Nov 20, 2024
1 parent cbbe657 commit 91348ad
Show file tree
Hide file tree
Showing 12 changed files with 2,288 additions and 185 deletions.
2 changes: 1 addition & 1 deletion nautilus_core/analysis/src/python/statistics/long_ratio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ impl LongRatio {
}

#[pyo3(name = "calculate_from_positions")]
fn py_calculate_from_positions(&mut self, positions: Vec<Position>) -> Option<String> {
fn py_calculate_from_positions(&mut self, positions: Vec<Position>) -> Option<f64> {
self.calculate_from_positions(&positions)
}
}
20 changes: 11 additions & 9 deletions nautilus_core/analysis/src/statistics/long_ratio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ impl LongRatio {
}

impl PortfolioStatistic for LongRatio {
type Item = String;
type Item = f64;

fn name(&self) -> String {
stringify!(LongRatio).to_string()
Expand All @@ -55,7 +55,9 @@ impl PortfolioStatistic for LongRatio {
.collect();

let value = longs.len() as f64 / positions.len() as f64;
Some(format!("{:.1$}", value, self.precision))

let scale = 10f64.powi(self.precision as i32);
Some((value * scale).round() / scale)
}
}

Expand Down Expand Up @@ -131,7 +133,7 @@ mod tests {

let result = long_ratio.calculate_from_positions(&positions);
assert!(result.is_some());
assert_eq!(result.unwrap(), "1.00");
assert_eq!(result.unwrap(), 1.00);
}

#[test]
Expand All @@ -145,7 +147,7 @@ mod tests {

let result = long_ratio.calculate_from_positions(&positions);
assert!(result.is_some());
assert_eq!(result.unwrap(), "0.00");
assert_eq!(result.unwrap(), 0.00);
}

#[test]
Expand All @@ -160,7 +162,7 @@ mod tests {

let result = long_ratio.calculate_from_positions(&positions);
assert!(result.is_some());
assert_eq!(result.unwrap(), "0.50");
assert_eq!(result.unwrap(), 0.50);
}

#[test]
Expand All @@ -174,7 +176,7 @@ mod tests {

let result = long_ratio.calculate_from_positions(&positions);
assert!(result.is_some());
assert_eq!(result.unwrap(), "0.667");
assert_eq!(result.unwrap(), 0.667);
}

#[test]
Expand All @@ -184,7 +186,7 @@ mod tests {

let result = long_ratio.calculate_from_positions(&positions);
assert!(result.is_some());
assert_eq!(result.unwrap(), "1.00");
assert_eq!(result.unwrap(), 1.00);
}

#[test]
Expand All @@ -194,7 +196,7 @@ mod tests {

let result = long_ratio.calculate_from_positions(&positions);
assert!(result.is_some());
assert_eq!(result.unwrap(), "0.00");
assert_eq!(result.unwrap(), 0.00);
}

#[test]
Expand All @@ -208,7 +210,7 @@ mod tests {

let result = long_ratio.calculate_from_positions(&positions);
assert!(result.is_some());
assert_eq!(result.unwrap(), "1");
assert_eq!(result.unwrap(), 1.00);
}

#[test]
Expand Down
102 changes: 100 additions & 2 deletions nautilus_core/common/src/cache/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,18 +44,21 @@ use nautilus_model::{
enums::{AggregationSource, OmsType, OrderSide, PositionSide, PriceType, TriggerType},
identifiers::{
AccountId, ClientId, ClientOrderId, ComponentId, ExecAlgorithmId, InstrumentId,
OrderListId, PositionId, StrategyId, Venue, VenueOrderId,
OrderListId, PositionId, StrategyId, Symbol, Venue, VenueOrderId,
},
instruments::{any::InstrumentAny, synthetic::SyntheticInstrument},
orderbook::book::OrderBook,
orders::{any::OrderAny, list::OrderList},
position::Position,
types::{currency::Currency, price::Price, quantity::Quantity},
};
use rust_decimal::Decimal;
use serde::{Deserialize, Serialize};
use ustr::Ustr;

use crate::{enums::SerializationEncoding, msgbus::database::DatabaseConfig};
use crate::{
enums::SerializationEncoding, msgbus::database::DatabaseConfig, xrate::get_exchange_rate,
};

/// Configuration for `Cache` instances.
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
Expand Down Expand Up @@ -1142,6 +1145,11 @@ impl Cache {
database.add_instrument(&instrument)?;
}

// match instrument {
// InstrumentAny::CurrencyPair(_) | InstrumentAny::CryptoPerpetual(_) => {}
// _ => {}
// }

self.instruments.insert(instrument.id(), instrument);
Ok(())
}
Expand Down Expand Up @@ -2474,6 +2482,81 @@ impl Cache {
self.bar_count(bar_type) > 0
}

#[must_use]
pub fn get_xrate(
&self,
venue: Venue,
from_currency: Currency,
to_currency: Currency,
price_type: PriceType,
) -> Decimal {
if from_currency == to_currency {
return Decimal::ONE;
}

let (bid_quote, ask_quote) = self.build_quote_table(&venue);

// TODO: improve error and complete this fn
get_exchange_rate(from_currency, to_currency, price_type, bid_quote, ask_quote)
}

fn build_quote_table(
&self,
venue: &Venue,
) -> (HashMap<Symbol, Decimal>, HashMap<Symbol, Decimal>) {
let mut bid_quotes = HashMap::new();
let mut ask_quotes = HashMap::new();

for instrument_id in self.instruments.keys() {
if instrument_id.venue != *venue {
continue;
}

let (bid_price, ask_price) = if let Some(ticks) = self.quotes.get(instrument_id) {
// Use quote ticks if available
if let Some(tick) = ticks.front() {
(tick.bid_price, tick.ask_price)
} else {
continue; // Empty ticks vector
}
} else {
// Fall back to bars if no quotes available
let bid_bar = self
.bars
.iter()
.find(|(k, _)| {
k.instrument_id() == *instrument_id
&& matches!(k.spec().price_type, PriceType::Bid)
})
.map(|(_, v)| v);

let ask_bar = self
.bars
.iter()
.find(|(k, _)| {
k.instrument_id() == *instrument_id
&& matches!(k.spec().price_type, PriceType::Ask)
})
.map(|(_, v)| v);

match (bid_bar, ask_bar) {
(Some(bid), Some(ask)) => {
let bid_price = bid.front().unwrap().close;
let ask_price = ask.front().unwrap().close;

(bid_price, ask_price)
}
_ => continue, // Missing either bid or ask bar
}
};

bid_quotes.insert(instrument_id.symbol, bid_price.as_decimal());
ask_quotes.insert(instrument_id.symbol, ask_price.as_decimal());
}

(bid_quotes, ask_quotes)
}

// -- INSTRUMENT QUERIES ----------------------------------------------------------------------

/// Returns a reference to the instrument for the given `instrument_id` (if found).
Expand Down Expand Up @@ -2554,6 +2637,12 @@ impl Cache {
self.accounts.get(account_id)
}

/// Returns a mutable reference to the account for the given `account_id` (if found).
#[must_use]
pub fn mut_account(&mut self, account_id: &AccountId) -> Option<&mut AccountAny> {
self.accounts.get_mut(account_id)
}

/// Returns a reference to the account for the given `venue` (if found).
#[must_use]
pub fn account_for_venue(&self, venue: &Venue) -> Option<&AccountAny> {
Expand All @@ -2563,6 +2652,15 @@ impl Cache {
.and_then(|account_id| self.accounts.get(account_id))
}

/// Returns a reference to the account for the given `venue` (if found).
#[must_use]
pub fn mut_account_for_venue(&mut self, venue: &Venue) -> Option<&mut AccountAny> {
self.index
.venue_account
.get(venue)
.and_then(|account_id| self.accounts.get_mut(account_id))
}

/// Returns a reference to the account ID for the given `venue` (if found).
#[must_use]
pub fn account_id(&self, venue: &Venue) -> Option<&AccountId> {
Expand Down
Loading

0 comments on commit 91348ad

Please sign in to comment.