Compare commits
4 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
c3e1b50b5f | 3 years ago |
|
|
7fd3d80504 | 3 years ago |
|
|
c3e62e36bb | 3 years ago |
|
|
4fb67445a9 | 3 years ago |
@ -1,11 +1,29 @@ |
||||
mod equity; |
||||
mod crypto; |
||||
mod options; |
||||
mod price_history; |
||||
mod data_service; |
||||
|
||||
pub enum AssetDataObject { |
||||
Equity(equity::Equity), |
||||
Crypro(crypto::Crypto), |
||||
OptionContract(options::OptionContract), |
||||
pub mod quotes; |
||||
pub mod options; |
||||
pub mod timeseries; |
||||
|
||||
use chrono::{DateTime, Utc}; |
||||
use super::DynResult; |
||||
|
||||
|
||||
pub trait TimeStamp { |
||||
fn timestamp(&self) -> DateTime<Utc>; |
||||
} |
||||
pub trait Volume { |
||||
fn volume(&self) -> Option<u64>; |
||||
} |
||||
|
||||
|
||||
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,67 @@ |
||||
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
|
||||
} |
||||
|
||||
pub trait HOLC { |
||||
fn high(&self) -> f64; |
||||
fn open(&self) -> f64; |
||||
fn low(&self) -> f64; |
||||
fn close(&self) -> f64; |
||||
} |
||||
///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,131 @@ |
||||
use chrono::{DateTime, Utc}; |
||||
use super::{Volume, TimeStamp, DynResult}; |
||||
use polars::{prelude::DataFrame, df, prelude::{NamedFrom}}; |
||||
use super::quotes::HOLC; |
||||
use probability::prelude::*; |
||||
|
||||
#[derive(Clone, Debug)] |
||||
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 fn new(h: f64, o: f64, l: f64, c: f64, v: Option<u64>, t: DateTime<Utc>) -> Self { |
||||
Candle { |
||||
high : h, |
||||
open : o, |
||||
low : l, |
||||
close: c, |
||||
volume : v, |
||||
timestamp : t |
||||
} |
||||
} |
||||
} |
||||
impl HOLC for Candle { |
||||
fn high(&self) -> f64 { self.high } |
||||
fn open(&self) -> f64 { self.open } |
||||
fn low(&self) -> f64 { self.low } |
||||
fn close(&self) -> f64 { self.close} |
||||
} |
||||
impl TimeStamp for Candle { |
||||
fn timestamp(&self) -> DateTime<Utc> { |
||||
self.timestamp |
||||
} |
||||
} |
||||
|
||||
|
||||
|
||||
pub struct TimeSeries { |
||||
pub candles: Vec<Candle> |
||||
} |
||||
impl TimeSeries { |
||||
pub 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 into_vec(self) -> Vec<Candle> { |
||||
return self.candles |
||||
} |
||||
pub fn as_vec(&self) -> Vec<Candle>{ |
||||
return self.candles.clone() |
||||
} |
||||
pub fn generate_random(n_datapoints: usize, mut start_price: f64) -> Self { |
||||
|
||||
let mut data: Vec<Candle> = vec![]; |
||||
|
||||
let inter_day_dist = Gaussian::new(1.0043,0.021); |
||||
let mut source = source::default(420); |
||||
let mut inter_sampler = Independent(&inter_day_dist, &mut source); |
||||
|
||||
let intra_day_dist = Gaussian::new(1.003,0.011); |
||||
let mut source2 = source::default(69); |
||||
let mut intra_sampler = Independent(&intra_day_dist, &mut source2); |
||||
|
||||
let day_moves = inter_sampler.take(n_datapoints).collect::<Vec<_>>(); |
||||
let intraday_moves = intra_sampler.take(n_datapoints * 3).collect::<Vec<_>>(); |
||||
|
||||
for n in 0..n_datapoints { |
||||
|
||||
let close = start_price * day_moves[n]; |
||||
data.push( Candle::new(start_price * intraday_moves[n], start_price, start_price * intraday_moves[n+1], close, Some((18183.0 * intraday_moves[n+3]) as u64), Utc::now())); |
||||
start_price = close; |
||||
} |
||||
TimeSeries { candles: data } |
||||
} |
||||
} |
||||
|
||||
|
||||
|
||||
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 |
||||
)?) |
||||
|
||||
} |
||||
|
||||
pub fn sample_timeseries() { |
||||
|
||||
} |
||||
@ -0,0 +1,3 @@ |
||||
pub mod ma; |
||||
pub mod rsi; |
||||
pub mod macd; |
||||
@ -0,0 +1,42 @@ |
||||
use crate::data::quotes::HOLC; |
||||
|
||||
|
||||
pub fn simple_moving_avg<C: HOLC> (data: Vec<C>, period: usize) -> Vec<f64> { |
||||
assert!(data.len() >= period, "Cannot create SMA! : Data is shorter than requested period."); |
||||
let mut ma_data = vec![]; |
||||
let n: f64 = period as f64; |
||||
// Get the initial average value
|
||||
let mut avg = data[..period].iter().fold(0.0, |acc, d| acc + d.close()) / n; |
||||
ma_data.push(avg); |
||||
// calculate the rest of the averages going forward
|
||||
for (i, d) in data[period..].iter().enumerate() { |
||||
// subtract the data that is no longer part of the period
|
||||
// Not that i corresponds to the index of data 1 period away since we are starting
|
||||
// iteraction 1 period in. This means it's perfect for getting the oldest data.
|
||||
avg -= data[i].close()/n; |
||||
// add the new data to the average
|
||||
avg += d.close() / n; |
||||
ma_data.push(avg); |
||||
} |
||||
ma_data |
||||
} |
||||
|
||||
fn cur_ema(closing_price: f64, prev_ema: f64, smoothing: f64) -> f64 { |
||||
(closing_price * smoothing) + (prev_ema * (1.0 - smoothing)) |
||||
} |
||||
|
||||
pub fn exponential_moving_average<C: HOLC> (data: Vec<C>, period: usize) -> Vec<f64> { |
||||
assert!(data.len() >= period + 1, "EMA requires period + 1 # of datapoints!"); |
||||
let mut ema_data = vec![]; |
||||
let n: f64 = period as f64; |
||||
// Get the average closing price over the original period
|
||||
let ma = data[..period].iter().fold(0.0, |acc, d| acc + d.close()) / n; |
||||
// Calculates our weighthing factor (using 2 as base)
|
||||
let smoothing = 2.0 / (n + 1.0); |
||||
for (i, d) in data[period..].iter().enumerate() { |
||||
// Use the previously calced MA for the first iteration
|
||||
if i == 0 {ema_data.push(cur_ema(d.close(), ma, smoothing)); continue;} |
||||
ema_data.push(cur_ema(d.close(), *ema_data.last().unwrap(), smoothing)); |
||||
} |
||||
ema_data |
||||
} |
||||
@ -0,0 +1,35 @@ |
||||
use crate::indicators::ma::exponential_moving_average; |
||||
use crate::data::quotes::HOLC; |
||||
use crate::data::TimeStamp; |
||||
|
||||
pub struct MACD { |
||||
upperBand: Vec<f64>, |
||||
lowerBand: Vec<f64>, |
||||
signalLine: Vec<f64>, |
||||
} |
||||
impl MACD { |
||||
pub fn new<C: HOLC + TimeStamp + Clone>(data: Vec<C>, upperBand: Option<usize>, lowerBand: Option<usize>, signalBand: Option<usize>) { |
||||
// This is going to need a custom implementation. It's not efficent to clone and iterate through the data 3 seperate times
|
||||
let ub = upperBand.unwrap_or(26); |
||||
let lb = lowerBand.unwrap_or(12); |
||||
let sb = signalBand.unwrap_or(9); |
||||
|
||||
let u_ema = exponential_moving_average(data.clone(), ub); |
||||
let l_ema = exponential_moving_average(data.clone(), lb); |
||||
let s_ema = exponential_moving_average(data.clone(), sb); |
||||
|
||||
println!("u_ema = {:?}", u_ema); |
||||
println!("u_ema.len() = {:?}", u_ema.len()); |
||||
|
||||
println!("l_ema = {:?}", l_ema); |
||||
println!("l_ema.len() = {:?}", l_ema.len()); |
||||
|
||||
println!("s_ema = {:?}", s_ema); |
||||
println!("s_ema.len() = {:?}", s_ema.len()); |
||||
} |
||||
} |
||||
|
||||
|
||||
fn moving_average_convergence_divergence<C: HOLC>(data: Vec<C>) { |
||||
|
||||
} |
||||
@ -0,0 +1,45 @@ |
||||
use crate::data::quotes::HOLC; |
||||
|
||||
pub fn relative_strength_index<C: HOLC>(data: Vec<C>, period: usize) -> Vec<f64> { |
||||
assert!(data.len() >= period + 2); |
||||
let mut rsi_data: Vec<f64> = vec![]; |
||||
let n = period as f64; |
||||
|
||||
let mut g_avg = 0.0; |
||||
let mut l_avg = 0.0; |
||||
|
||||
for (i, d) in data[1..period+1].iter().enumerate() { |
||||
let chg = d.close() - data[i].close(); |
||||
if chg >= 0.0 {g_avg += chg;} |
||||
else if chg <= 0.0 { l_avg += chg.abs();} |
||||
|
||||
if i == period -1 { |
||||
g_avg /=n; |
||||
l_avg /=n; |
||||
rsi_data.push(100.0 - (100.0/(1.0+((g_avg)/(l_avg))))); |
||||
} |
||||
} |
||||
// This is magic. Don't touch it. The periods just work.
|
||||
|
||||
for (i, d) in data[period+1..].iter().enumerate() { |
||||
|
||||
let chg = d.close() - data[period + i ].close(); |
||||
|
||||
if chg > 0.0 { |
||||
g_avg = (g_avg * (n - 1.0) + chg) / n; |
||||
l_avg = (l_avg * (n - 1.0) + 0.0) / n; |
||||
} else if chg < 0.0 { |
||||
g_avg = (g_avg * (n - 1.0) + 0.0) / n; |
||||
l_avg = (l_avg * (n - 1.0) + chg.abs()) / n; |
||||
} |
||||
else { |
||||
g_avg = (g_avg * (n - 1.0) + 0.0) / n; |
||||
l_avg = (l_avg * (n - 1.0) + 0.0) / n; |
||||
} |
||||
|
||||
rsi_data.push(100.0 - (100.0/(1.0+((g_avg)/(l_avg))))); |
||||
|
||||
} |
||||
rsi_data |
||||
|
||||
} |
||||
@ -1,47 +1,15 @@ |
||||
use crate::data::AssetDataObject; |
||||
use crate::data::quotes::AssetIdentifier; |
||||
|
||||
|
||||
pub enum Direction { |
||||
enum OrderDirection { |
||||
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 |
||||
|
||||
struct Order { |
||||
asset: AssetIdentifier, |
||||
transaction_price: f64, |
||||
quantity: i32, |
||||
} |
||||
@ -0,0 +1,126 @@ |
||||
#[cfg(test)] |
||||
mod tests { |
||||
use crate::data::timeseries::{Candle, TimeSeries}; |
||||
use crate::indicators::ma::exponential_moving_average; |
||||
use crate::indicators::rsi::relative_strength_index; |
||||
use crate::indicators::macd::MACD; |
||||
use crate::indicators::{ma}; |
||||
use crate::data::quotes::{HOLC}; |
||||
use chrono::Utc; |
||||
|
||||
|
||||
#[test] |
||||
fn sma() { |
||||
let data = vec![ |
||||
Candle::new(0.0,0.0,0.0, 4.0, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 8.0, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 11.0, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 8.0, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 14.0, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 6.0, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 6.0, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 1.0, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 4.0, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 4.0, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 9.0, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 7.0, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 12.0, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 5.0, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 1.0, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 10.0, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 5.0, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 9.0, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 6.0, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 2.0, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 8.0, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 9.0, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 11.0, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 14.0, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 9.0, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 12.0, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 4.0, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 6.0, None,Utc::now()), |
||||
]; |
||||
println!("data.len() = {:?}", data.len()); |
||||
|
||||
let sma_d = ma::simple_moving_avg(data, 3); |
||||
println!("sma_d = {:?}", sma_d); |
||||
|
||||
} |
||||
#[test] |
||||
fn ema(){ |
||||
let data = vec![ |
||||
Candle::new(0.0,0.0,0.0, 4.0, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 8.0, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 11.0, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 8.0, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 14.0, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 6.0, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 6.0, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 1.0, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 4.0, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 4.0, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 9.0, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 7.0, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 12.0, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 5.0, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 1.0, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 10.0, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 5.0, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 9.0, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 6.0, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 2.0, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 8.0, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 9.0, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 11.0, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 14.0, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 9.0, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 12.0, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 4.0, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 6.0, None,Utc::now()), |
||||
]; |
||||
|
||||
let ema_d = exponential_moving_average(data, 3); |
||||
println!("ema_d = {:?}", ema_d); |
||||
} |
||||
|
||||
#[test] |
||||
fn rsi() { |
||||
let data = vec![ |
||||
Candle::new(0.0,0.0,0.0, 140.06, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 144.28, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 147.64, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 150.6, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 151.92, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 154.79, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 152.61, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 150.26, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 150.47, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 146.68, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 145.14, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 148.1, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 148.82, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 148.91, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 147.21, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 142.84, None,Utc::now()), |
||||
Candle::new(0.0,0.0,0.0, 145.48, None,Utc::now()), |
||||
|
||||
]; |
||||
|
||||
let rsi_d = relative_strength_index(data, 14); |
||||
println!("rsi_d = {:?}", rsi_d); |
||||
} |
||||
#[test] |
||||
fn candle_gen() { |
||||
let data = TimeSeries::generate_random(50, 100.0); |
||||
for c in data.candles.iter() { |
||||
println!("c = {:?}", c); |
||||
} |
||||
} |
||||
#[test] |
||||
fn macd(){ |
||||
let data = TimeSeries::generate_random(50, 100.0); |
||||
|
||||
let x = MACD::new(data.candles, None,None,None); |
||||
} |
||||
} |
||||
Loading…
Reference in new issue