Overhauled data module to revolve around traits rather than standardized models | Added timeseries/candle struct and traits
parent
1ae5eb25db
commit
4fb67445a9
@ -1,11 +1,32 @@ |
|||||||
mod equity; |
pub mod quotes; |
||||||
mod crypto; |
pub mod options; |
||||||
mod options; |
pub mod timeseries; |
||||||
mod price_history; |
|
||||||
mod data_service; |
use chrono::{DateTime, Utc}; |
||||||
|
use super::DynResult; |
||||||
pub enum AssetDataObject { |
|
||||||
Equity(equity::Equity), |
|
||||||
Crypro(crypto::Crypto), |
pub trait TimeStamp { |
||||||
OptionContract(options::OptionContract), |
fn timestamp(&self) -> DateTime<Utc>; |
||||||
|
} |
||||||
|
pub trait Volume { |
||||||
|
fn volume(&self) -> Option<u64>; |
||||||
|
} |
||||||
|
|
||||||
|
pub fn to_datetime(timestamp: i64) { |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
pub enum Period { |
||||||
|
Second, |
||||||
|
Minute, |
||||||
|
Hour, |
||||||
|
Day, |
||||||
|
TradeDay, |
||||||
|
Week, |
||||||
|
TradeWeek, |
||||||
|
Month, |
||||||
|
Year, |
||||||
|
Ytd, |
||||||
|
AssetLife |
||||||
} |
} |
||||||
@ -1,49 +0,0 @@ |
|||||||
use std::fmt::Display; |
|
||||||
use crate::DynResult; |
|
||||||
|
|
||||||
#[derive(Debug)] |
|
||||||
pub struct CryptoError { |
|
||||||
_error: String |
|
||||||
} |
|
||||||
impl CryptoError { |
|
||||||
pub fn new(error_msg: &str) -> Self { |
|
||||||
CryptoError { _error: error_msg.to_owned() } |
|
||||||
} |
|
||||||
} |
|
||||||
impl Display for CryptoError { |
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
|
||||||
write!(f, "Crypto Error Placeholder") |
|
||||||
} |
|
||||||
} |
|
||||||
impl std::error::Error for CryptoError {} |
|
||||||
|
|
||||||
#[derive(Debug)] |
|
||||||
pub struct Crypto { |
|
||||||
pub symbol: String, |
|
||||||
pub exchange: Option<String>, |
|
||||||
pub base_crypto: String, // being purchased (top)
|
|
||||||
pub quote_crypto: String, |
|
||||||
pub bid: f64, |
|
||||||
pub mid: f64, |
|
||||||
pub ask: f64, |
|
||||||
pub last: Option<f64>, |
|
||||||
pub bid_size: Option<usize>, |
|
||||||
pub ask_size: Option<usize>, |
|
||||||
pub volume: Option<usize>, |
|
||||||
pub high: Option<f64>, |
|
||||||
pub open: Option<f64>, |
|
||||||
pub low: Option<f64>, |
|
||||||
pub close: Option<f64>, |
|
||||||
pub marginable: Option<bool>, |
|
||||||
pub quote_time: i64 |
|
||||||
} |
|
||||||
impl Crypto { |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
pub trait ToCrypto { |
|
||||||
fn to_crypto(&self) -> DynResult<Crypto>; |
|
||||||
} |
|
||||||
@ -1,58 +0,0 @@ |
|||||||
use crate::data::*; |
|
||||||
use crate::DynResult; |
|
||||||
|
|
||||||
/* |
|
||||||
A data service must implement at lease one of the following traits |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Important to note that Paramaters can be typed as Option<P> during implemenation |
|
||||||
and that the actual strucut/type passed into these is flexable. This should allow |
|
||||||
each services library to implement a paramates trait that works for them, or
|
|
||||||
leave paramaters as 'None' |
|
||||||
|
|
||||||
This way you can lock down what paramaters are required for each indiviudual service |
|
||||||
while still allowing the RustyTrade framework to reliably obtain the expected struct |
|
||||||
from each trait interface. |
|
||||||
|
|
||||||
struct ExamplePriceHistoryParams { |
|
||||||
start_date: i64, |
|
||||||
end_date: i64 |
|
||||||
} |
|
||||||
|
|
||||||
struct ExampleDataService {}; |
|
||||||
impl GetPriceHistory for ExampleDataService { |
|
||||||
type Paramaters = ExamplePriceHistoryParmas; |
|
||||||
fn get_price_history(&mut self, paramaters: Self::Paramaters)-> DynResult<PriceHistory> { |
|
||||||
|
|
||||||
}
|
|
||||||
} |
|
||||||
|
|
||||||
*/ |
|
||||||
pub trait GetEquity { |
|
||||||
type Paramaters; |
|
||||||
fn get_equity(&mut self, paramaters: Self::Paramaters) -> DynResult<equity::Equity>; |
|
||||||
} |
|
||||||
pub trait GetCrypto { |
|
||||||
type Paramaters; |
|
||||||
fn get_crypto(&mut self, paramaters: Self::Paramaters) -> DynResult<crypto::Crypto>; |
|
||||||
} |
|
||||||
pub trait GetOptionContract { |
|
||||||
type Paramaters; |
|
||||||
fn get_option_contract(&mut self, paramaters: Self::Paramaters) -> DynResult<options::OptionContract>; |
|
||||||
} |
|
||||||
pub trait GetOptionChain { |
|
||||||
type Paramaters; |
|
||||||
fn get_options_chain_vec(&mut self, paramaters: Self::Paramaters) -> DynResult<Vec<options::OptionContract>>; |
|
||||||
fn get_options_chain_dataframe(&mut self, paramaters: Self::Paramaters) -> DynResult<options::OptionChainDataFrame>; |
|
||||||
} |
|
||||||
pub trait GetPriceHistory{ |
|
||||||
type Paramaters; |
|
||||||
fn get_price_history(&mut self, paramaters: Self::Paramaters)-> DynResult<price_history::PriceHistory>; |
|
||||||
} |
|
||||||
|
|
||||||
@ -1,51 +0,0 @@ |
|||||||
use std::fmt::Display; |
|
||||||
use crate::DynResult; |
|
||||||
|
|
||||||
#[derive(Debug)] |
|
||||||
pub struct EquityError { |
|
||||||
error: String |
|
||||||
} |
|
||||||
impl EquityError { |
|
||||||
pub fn new(error_msg: &str) -> Self { |
|
||||||
EquityError { error: error_msg.to_owned() } |
|
||||||
} |
|
||||||
} |
|
||||||
impl Display for EquityError { |
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
|
||||||
write!(f, "Equity Error Placeholder") |
|
||||||
} |
|
||||||
} |
|
||||||
impl std::error::Error for EquityError {} |
|
||||||
|
|
||||||
#[derive(Debug)] |
|
||||||
pub struct Equity { |
|
||||||
pub symbol: String, |
|
||||||
pub cusip : Option<String>, |
|
||||||
pub exchange: Option<String>, |
|
||||||
pub bid: f64, |
|
||||||
pub mid: f64, |
|
||||||
pub ask: f64, |
|
||||||
pub last: Option<f64>, |
|
||||||
pub bid_size: Option<usize>, |
|
||||||
pub ask_size: Option<usize>, |
|
||||||
pub volume: Option<usize>, |
|
||||||
pub high: Option<f64>, |
|
||||||
pub open: Option<f64>, |
|
||||||
pub low: Option<f64>, |
|
||||||
pub close: Option<f64>, |
|
||||||
pub shortable: Option<bool>, |
|
||||||
pub marginable: Option<bool>, |
|
||||||
pub quote_time: i64 |
|
||||||
} |
|
||||||
impl Equity { |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
pub trait ToEquity { |
|
||||||
fn to_equity(&self) -> DynResult<Equity>; |
|
||||||
} |
|
||||||
@ -1,56 +0,0 @@ |
|||||||
use polars::{prelude::DataFrame, df, prelude::{NamedFrom}}; |
|
||||||
|
|
||||||
use crate::DynResult; |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
pub struct Candle { |
|
||||||
pub high: f64, |
|
||||||
pub open: f64, |
|
||||||
pub low: f64, |
|
||||||
pub close: f64, |
|
||||||
pub volume: Option<u64>, |
|
||||||
pub timestamp: i64 // mls since epoch
|
|
||||||
} |
|
||||||
impl Candle { |
|
||||||
pub fn new(high: f64, open: f64, low: f64, close: f64, volume: Option<u64>, timestamp: i64) -> Self { |
|
||||||
Candle { high, open, low, close, volume, timestamp } |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
pub struct PriceHistory { |
|
||||||
symbol: String, |
|
||||||
candles: Vec<Candle> |
|
||||||
} |
|
||||||
|
|
||||||
pub trait ToPriceHistory { |
|
||||||
fn to_pricehistorty(&self) -> DynResult<PriceHistory>; |
|
||||||
} |
|
||||||
|
|
||||||
pub fn create_timeseries_dataframe(timeseries_data: &Vec<Candle>) -> DynResult<DataFrame> { |
|
||||||
let mut high = vec![]; |
|
||||||
let mut open = vec![]; |
|
||||||
let mut low = vec![]; |
|
||||||
let mut close = vec![]; |
|
||||||
let mut volume = vec![]; |
|
||||||
let mut timestamp = vec![]; |
|
||||||
|
|
||||||
for candle in timeseries_data { |
|
||||||
high.push(candle.high); |
|
||||||
open.push(candle.open); |
|
||||||
low.push(candle.low); |
|
||||||
close.push(candle.close); |
|
||||||
volume.push(candle.volume); |
|
||||||
timestamp.push(candle.timestamp); |
|
||||||
} |
|
||||||
|
|
||||||
Ok(df!( |
|
||||||
"High" => &high, |
|
||||||
"Open" => &open, |
|
||||||
"Low" => &low, |
|
||||||
"Close"=> &close, |
|
||||||
"Volume"=> &volume, |
|
||||||
"TimeStamp" => ×tamp |
|
||||||
)?) |
|
||||||
|
|
||||||
} |
|
||||||
@ -0,0 +1,60 @@ |
|||||||
|
use chrono::{Utc, DateTime}; |
||||||
|
use super::Period; |
||||||
|
use super::options::OptionKind; |
||||||
|
|
||||||
|
pub enum AssetIdentifier{ |
||||||
|
Ticker(String), |
||||||
|
Cusip(String), |
||||||
|
Other(String) |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
///Information about what this quote it, where it came from and when
|
||||||
|
///
|
||||||
|
pub trait QuoteData { |
||||||
|
/// Gives the symbol/ticker/cusip of this asset
|
||||||
|
fn asset_symbol(&self) -> AssetIdentifier; |
||||||
|
/// Gives the timestamp of when the quote data is valid
|
||||||
|
fn quote_time(&self) -> DateTime<Utc>; |
||||||
|
/// Gives the timestamp of when the quote was created
|
||||||
|
fn retrieve_time(&self) ->DateTime<Utc>; |
||||||
|
/// Gives the exchange which the data was sources from
|
||||||
|
fn exchange(&self) -> Option<String>; |
||||||
|
// TO DO: Gives the datasource used
|
||||||
|
} |
||||||
|
///Standard volume information
|
||||||
|
///
|
||||||
|
pub trait VolumeData { |
||||||
|
/// Gives the period over which this volume is valid
|
||||||
|
fn volume_period(&self) -> Period; |
||||||
|
/// Total volume seem in that period
|
||||||
|
fn total_volume(&self) -> u64; |
||||||
|
/// Gives the current bid size of the asset
|
||||||
|
fn bid_size(&self) -> u64; |
||||||
|
// Gives the current as size of the asset
|
||||||
|
fn ask_size(&self) -> u64; |
||||||
|
// Gives the size of the last trade
|
||||||
|
fn last_size(&self) -> Option<u64>; |
||||||
|
} |
||||||
|
///Standard information about price spread
|
||||||
|
///
|
||||||
|
pub trait PriceSpreadData { |
||||||
|
/// Give the bid price of an asset
|
||||||
|
fn bid(&self) -> f64; |
||||||
|
/// Gives the mid price of an asset
|
||||||
|
fn mid(&self) -> f64; |
||||||
|
/// Gives the ask price of an asset
|
||||||
|
fn ask(&self) -> f64; |
||||||
|
} |
||||||
|
pub trait Marginable { |
||||||
|
/// Gives the margin cost as a yearly interest cost. Returns none if not marginable
|
||||||
|
fn margin_cost(&self) -> Option<f64>; |
||||||
|
/// Returns true if we can use margin on this instrument
|
||||||
|
fn is_marginable(&self) -> bool; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
pub trait CryptoData { |
||||||
|
fn base_crypto(&self) -> String; |
||||||
|
fn quote_crypto(&self) -> String; |
||||||
|
} |
||||||
@ -0,0 +1,78 @@ |
|||||||
|
use chrono::{DateTime, Utc}; |
||||||
|
use super::{Volume, TimeStamp, DynResult}; |
||||||
|
use polars::{prelude::DataFrame, df, prelude::{NamedFrom}}; |
||||||
|
|
||||||
|
|
||||||
|
pub struct Candle { |
||||||
|
pub high: f64, |
||||||
|
pub open: f64, |
||||||
|
pub low: f64, |
||||||
|
pub close: f64, |
||||||
|
pub volume: Option<u64>, |
||||||
|
pub timestamp: DateTime<Utc> |
||||||
|
} |
||||||
|
impl Candle { |
||||||
|
fn from<SourceData>(data: SourceData) -> Self |
||||||
|
where SourceData: HOLC + TimeStamp + Volume { |
||||||
|
Candle { high: data.high(), |
||||||
|
open: data.open(),
|
||||||
|
low: data.low(),
|
||||||
|
close: data.close(),
|
||||||
|
volume: data.volume(),
|
||||||
|
timestamp: data.timestamp(),
|
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
pub trait HOLC { |
||||||
|
fn high(&self) -> f64; |
||||||
|
fn open(&self) -> f64; |
||||||
|
fn low(&self) -> f64; |
||||||
|
fn close(&self) -> f64; |
||||||
|
} |
||||||
|
|
||||||
|
pub struct TimeSeries { |
||||||
|
candles: Vec<Candle> |
||||||
|
} |
||||||
|
impl TimeSeries { |
||||||
|
fn new(candles: Vec<Candle>) -> Self { |
||||||
|
TimeSeries { candles: candles } |
||||||
|
} |
||||||
|
fn from<C>(data: Vec<C>) -> Self |
||||||
|
where C: HOLC + TimeStamp + Volume |
||||||
|
{ |
||||||
|
let mut candles: Vec<Candle> = Vec::new(); |
||||||
|
for d in data { |
||||||
|
candles.push(Candle::from(d)) |
||||||
|
} |
||||||
|
TimeSeries::new(candles) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
pub fn create_timeseries_dataframe(timeseries_data: &Vec<Candle>) -> DynResult<DataFrame> { |
||||||
|
let mut high = vec![]; |
||||||
|
let mut open = vec![]; |
||||||
|
let mut low = vec![]; |
||||||
|
let mut close = vec![]; |
||||||
|
let mut volume = vec![]; |
||||||
|
let mut timestamp = vec![]; |
||||||
|
|
||||||
|
for candle in timeseries_data { |
||||||
|
high.push(candle.high); |
||||||
|
open.push(candle.open); |
||||||
|
low.push(candle.low); |
||||||
|
close.push(candle.close); |
||||||
|
volume.push(candle.volume); |
||||||
|
timestamp.push(candle.timestamp.timestamp_millis()); |
||||||
|
} |
||||||
|
|
||||||
|
Ok(df!( |
||||||
|
"High" => &high, |
||||||
|
"Open" => &open, |
||||||
|
"Low" => &low, |
||||||
|
"Close"=> &close, |
||||||
|
"Volume"=> &volume, |
||||||
|
"TimeStamp" => ×tamp |
||||||
|
)?) |
||||||
|
|
||||||
|
} |
||||||
@ -1,47 +0,0 @@ |
|||||||
use crate::data::AssetDataObject; |
|
||||||
|
|
||||||
|
|
||||||
pub enum Direction { |
|
||||||
Buy, |
|
||||||
Sell |
|
||||||
} |
|
||||||
impl ToString for Direction { |
|
||||||
fn to_string(&self) -> String { |
|
||||||
match &self { |
|
||||||
Self::Buy => "Buy".to_string(), |
|
||||||
Self::Sell => "Sell".to_string() |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
pub enum OrderType { |
|
||||||
Market, |
|
||||||
Limit, |
|
||||||
Stop, |
|
||||||
TrailingStop |
|
||||||
}
|
|
||||||
impl ToString for OrderType { |
|
||||||
fn to_string(&self) -> String { |
|
||||||
match &self { |
|
||||||
Self::Market => "Market".to_string(), |
|
||||||
Self::Limit => "Limit".to_string(), |
|
||||||
Self::Stop => "Stop".to_string(), |
|
||||||
Self::TrailingStop => "TrailingStop".to_string() |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
pub struct SimpleOrder { |
|
||||||
pub asset: AssetDataObject, |
|
||||||
pub price_to_pay: f64, |
|
||||||
pub direction: Direction, |
|
||||||
pub order_type: OrderType, |
|
||||||
pub good_until: i64, |
|
||||||
pub approved: bool |
|
||||||
} |
|
||||||
|
|
||||||
pub struct CompoundOrder { |
|
||||||
pub orders: Vec<SimpleOrder>, |
|
||||||
pub approved: bool |
|
||||||
|
|
||||||
} |
|
||||||
Loading…
Reference in new issue