adding comments bit of parralel
This commit is contained in:
parent
80ebde1e0b
commit
f344cd9d65
3
.github/workflows/build.yml
vendored
3
.github/workflows/build.yml
vendored
@ -105,7 +105,7 @@ jobs:
|
|||||||
toolchain: stable
|
toolchain: stable
|
||||||
|
|
||||||
- name: Build Docs
|
- name: Build Docs
|
||||||
run: cargo doc --no-deps --document-private-items
|
run: cargo doc --no-deps --document-private-items -F py,wasm,ffi
|
||||||
|
|
||||||
- name: Add redirect
|
- name: Add redirect
|
||||||
run: echo '<meta http-equiv="refresh" content="0;url=finlib/index.html">' > target/doc/index.html
|
run: echo '<meta http-equiv="refresh" content="0;url=finlib/index.html">' > target/doc/index.html
|
||||||
@ -160,6 +160,7 @@ jobs:
|
|||||||
uses: actions/setup-node@v2
|
uses: actions/setup-node@v2
|
||||||
with:
|
with:
|
||||||
node-version: 22
|
node-version: 22
|
||||||
|
registry-url: 'https://registry.npmjs.org' # This is just the default registry URL
|
||||||
|
|
||||||
- name: Publish
|
- name: Publish
|
||||||
working-directory: ./finlib-wasm/pkg
|
working-directory: ./finlib-wasm/pkg
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
//! FFI specific functionality to define the struct function interfaces in Python and WASM
|
||||||
|
|
||||||
#[cfg(feature = "py")]
|
#[cfg(feature = "py")]
|
||||||
pub mod py;
|
pub mod py;
|
||||||
#[cfg(feature = "wasm")]
|
#[cfg(feature = "wasm")]
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
//! Compound interest etc
|
||||||
|
|
||||||
pub fn compound_32(principal: f32, rate: f32, time: f32, n: f32) -> f32 {
|
pub fn compound_32(principal: f32, rate: f32, time: f32, n: f32) -> f32 {
|
||||||
principal * f32::powf( 1f32 + (rate / n), time * n)
|
principal * f32::powf( 1f32 + (rate / n), time * n)
|
||||||
|
@ -1,5 +1,33 @@
|
|||||||
|
//! # Quant finance functionality for Rust with FFIs to C/C++, C#, Python and WASM
|
||||||
|
|
||||||
pub mod interest;
|
pub mod interest;
|
||||||
pub mod stats;
|
pub mod stats;
|
||||||
pub mod util;
|
pub mod util;
|
||||||
pub mod risk;
|
pub mod risk;
|
||||||
pub mod ffi;
|
pub mod ffi;
|
||||||
|
|
||||||
|
#[cfg(feature = "parallel")]
|
||||||
|
use rayon::prelude::*;
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! gated_iter {
|
||||||
|
($x:expr) => {
|
||||||
|
{
|
||||||
|
$x.iter()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! gated_iter_mut {
|
||||||
|
($x:expr) => {
|
||||||
|
{
|
||||||
|
if cfg!(feature = "parallel") {
|
||||||
|
$x.par_iter_mut()
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$x.iter_mut()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
@ -1,3 +1,5 @@
|
|||||||
|
//! Calculating risk for a given asset or portfolio using Value at Risk, [`var`]
|
||||||
|
|
||||||
pub mod var;
|
pub mod var;
|
||||||
pub mod portfolio;
|
pub mod portfolio;
|
||||||
pub mod forecast;
|
pub mod forecast;
|
||||||
|
@ -5,12 +5,15 @@ use ndarray_stats::CorrelationExt;
|
|||||||
use wasm_bindgen::prelude::*;
|
use wasm_bindgen::prelude::*;
|
||||||
#[cfg(feature = "py")]
|
#[cfg(feature = "py")]
|
||||||
use pyo3::prelude::*;
|
use pyo3::prelude::*;
|
||||||
|
#[cfg(feature = "parallel")]
|
||||||
|
use rayon::prelude::*;
|
||||||
use statrs::distribution::{ContinuousCDF, Normal};
|
use statrs::distribution::{ContinuousCDF, Normal};
|
||||||
use crate::risk::forecast::{mean_investment, std_dev_investment};
|
use crate::risk::forecast::{mean_investment, std_dev_investment};
|
||||||
use crate::risk::var::varcovar::{investment_value_at_risk};
|
use crate::risk::var::varcovar::{investment_value_at_risk};
|
||||||
use crate::stats;
|
use crate::{stats};
|
||||||
use crate::util::roc::rates_of_change;
|
use crate::util::roc::rates_of_change;
|
||||||
|
|
||||||
|
/// Describes a Portfolio as a collection of [`PortfolioAsset`]s
|
||||||
#[cfg_attr(feature = "wasm", wasm_bindgen)]
|
#[cfg_attr(feature = "wasm", wasm_bindgen)]
|
||||||
#[cfg_attr(feature = "py", pyclass)]
|
#[cfg_attr(feature = "py", pyclass)]
|
||||||
#[cfg_attr(feature = "ffi", repr(C))]
|
#[cfg_attr(feature = "ffi", repr(C))]
|
||||||
@ -28,6 +31,7 @@ pub enum ValueType {
|
|||||||
RateOfChange
|
RateOfChange
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Describes a single instrument as a list of previous values with an associated portfolio proportion
|
||||||
#[cfg_attr(feature = "wasm", wasm_bindgen)]
|
#[cfg_attr(feature = "wasm", wasm_bindgen)]
|
||||||
#[cfg_attr(feature = "py", pyclass)]
|
#[cfg_attr(feature = "py", pyclass)]
|
||||||
#[cfg_attr(feature = "ffi", repr(C))]
|
#[cfg_attr(feature = "ffi", repr(C))]
|
||||||
@ -46,6 +50,7 @@ impl PortfolioAsset {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// If the asset's values have been given as absolute values, convert those to a percentage change between each
|
||||||
pub fn apply_rates_of_change(&mut self) {
|
pub fn apply_rates_of_change(&mut self) {
|
||||||
match self.value_type {
|
match self.value_type {
|
||||||
ValueType::Absolute => {
|
ValueType::Absolute => {
|
||||||
@ -56,6 +61,9 @@ impl PortfolioAsset {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the mean and standard deviation of the rates of change of an asset
|
||||||
|
///
|
||||||
|
/// returns (mean, std_dev)
|
||||||
pub fn get_mean_and_std(&self) -> Option<(f64, f64)> {
|
pub fn get_mean_and_std(&self) -> Option<(f64, f64)> {
|
||||||
match self.value_type {
|
match self.value_type {
|
||||||
ValueType::Absolute => {
|
ValueType::Absolute => {
|
||||||
@ -77,18 +85,32 @@ impl Portfolio {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return the proportions of a portfolio's assets
|
||||||
|
///
|
||||||
|
/// In a properly formed Portfolio these will add up to 1.0
|
||||||
pub fn get_asset_weight(&self) -> impl Iterator<Item=f64> + use<'_> {
|
pub fn get_asset_weight(&self) -> impl Iterator<Item=f64> + use<'_> {
|
||||||
self.assets
|
self.assets
|
||||||
.iter()
|
.iter()
|
||||||
.map(|x| x.portfolio_weight)
|
.map(|x| x.portfolio_weight)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Convert a portfolio of assets with absolute values to the percentage change in values
|
||||||
pub fn apply_rates_of_change(&mut self) {
|
pub fn apply_rates_of_change(&mut self) {
|
||||||
for asset in self.assets.iter_mut() {
|
#[cfg(feature = "parallel")]
|
||||||
asset.apply_rates_of_change();
|
{
|
||||||
|
self.assets.par_iter_mut().for_each(|asset| {
|
||||||
|
asset.apply_rates_of_change();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
#[cfg(not(feature = "parallel"))]
|
||||||
|
{
|
||||||
|
self.assets.iter_mut().for_each(|asset| {
|
||||||
|
asset.apply_rates_of_change();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Do all the assets in the portfolio have the same number of values (required to perform matrix operations)
|
||||||
pub fn valid_sizes(&self) -> bool {
|
pub fn valid_sizes(&self) -> bool {
|
||||||
let mut last_value_length: Option<usize> = None;
|
let mut last_value_length: Option<usize> = None;
|
||||||
|
|
||||||
@ -109,6 +131,7 @@ impl Portfolio {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Do the proportions of the assets in the portfolio add up to 100%?
|
||||||
pub fn valid_weights(&self) -> bool {
|
pub fn valid_weights(&self) -> bool {
|
||||||
let mut weight = 1f64;
|
let mut weight = 1f64;
|
||||||
|
|
||||||
@ -123,6 +146,7 @@ impl Portfolio {
|
|||||||
self.valid_sizes() && self.valid_weights()
|
self.valid_sizes() && self.valid_weights()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Format the asset values in the portfolio as a matrix such that statistical operations can be applied to it
|
||||||
pub fn get_matrix(&self) -> Option<Array2<f64>> {
|
pub fn get_matrix(&self) -> Option<Array2<f64>> {
|
||||||
if self.assets.is_empty() || !self.valid_sizes() {
|
if self.assets.is_empty() || !self.valid_sizes() {
|
||||||
return None;
|
return None;
|
||||||
@ -131,17 +155,34 @@ impl Portfolio {
|
|||||||
let column_count = self.assets.len();
|
let column_count = self.assets.len();
|
||||||
let row_count = self.assets[0].values.len();
|
let row_count = self.assets[0].values.len();
|
||||||
|
|
||||||
let matrix = Array2::from_shape_vec((column_count, row_count),
|
#[cfg(feature = "parallel")]
|
||||||
self.assets
|
{
|
||||||
.iter()
|
let matrix = Array2::from_shape_vec((column_count, row_count),
|
||||||
.map(|a| a.values.clone())
|
self.assets
|
||||||
.flatten()
|
.par_iter()
|
||||||
.collect::<Vec<f64>>()
|
.map(|a| a.values.clone())
|
||||||
).unwrap();
|
.flatten()
|
||||||
|
.collect::<Vec<f64>>()
|
||||||
|
).unwrap();
|
||||||
|
Some(matrix.into_owned())
|
||||||
|
}
|
||||||
|
#[cfg(not(feature = "parallel"))]
|
||||||
|
{
|
||||||
|
let matrix = Array2::from_shape_vec((column_count, row_count),
|
||||||
|
self.assets
|
||||||
|
.iter()
|
||||||
|
.map(|a| a.values.clone())
|
||||||
|
.flatten()
|
||||||
|
.collect::<Vec<f64>>()
|
||||||
|
).unwrap();
|
||||||
|
Some(matrix.into_owned())
|
||||||
|
}
|
||||||
|
|
||||||
Some(matrix.into_owned())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Calculate the mean and the standard deviation of a portfolio, taking into account the relative weights and covariance of the portfolio's assets
|
||||||
|
///
|
||||||
|
/// returns (mean, std_dev)
|
||||||
pub fn get_mean_and_std(&mut self) -> Option<(f64, f64)> {
|
pub fn get_mean_and_std(&mut self) -> Option<(f64, f64)> {
|
||||||
if !self.valid_sizes() {
|
if !self.valid_sizes() {
|
||||||
error!("Can't get portfolio mean and std dev because asset value counts arent't the same");
|
error!("Can't get portfolio mean and std dev because asset value counts arent't the same");
|
||||||
@ -178,8 +219,9 @@ impl Portfolio {
|
|||||||
Some((porfolio_mean_return, portfolio_stddev))
|
Some((porfolio_mean_return, portfolio_stddev))
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://www.interviewqs.com/blog/value-at-risk
|
/// For a given confidence rate (0.01, 0.05, 0.10) and initial investment value, calculate the parametric value at risk
|
||||||
|
///
|
||||||
|
/// https://www.interviewqs.com/blog/value-at-risk
|
||||||
pub fn value_at_risk(&mut self, confidence: f64, initial_investment: f64) -> Option<f64> {
|
pub fn value_at_risk(&mut self, confidence: f64, initial_investment: f64) -> Option<f64> {
|
||||||
match self.get_mean_and_std() {
|
match self.get_mean_and_std() {
|
||||||
None => None,
|
None => None,
|
||||||
@ -198,8 +240,9 @@ impl Portfolio {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://www.interviewqs.com/blog/value-at-risk
|
/// For a given confidence rate (0.01, 0.05, 0.10) calculate the percentage change in an investment
|
||||||
|
///
|
||||||
|
/// https://www.interviewqs.com/blog/value-at-risk
|
||||||
pub fn value_at_risk_percent(&mut self, confidence: f64) -> Option<f64> {
|
pub fn value_at_risk_percent(&mut self, confidence: f64) -> Option<f64> {
|
||||||
match self.get_mean_and_std() {
|
match self.get_mean_and_std() {
|
||||||
None => None,
|
None => None,
|
||||||
|
@ -1,2 +1,4 @@
|
|||||||
|
//! Calculate Value at Risk using either the [`historical`] or parametric [`varcovar`] methods for an asset or portfolio
|
||||||
|
|
||||||
pub mod historical;
|
pub mod historical;
|
||||||
pub mod varcovar;
|
pub mod varcovar;
|
||||||
|
@ -1,13 +1,9 @@
|
|||||||
mod covariance;
|
mod covariance;
|
||||||
pub use covariance::*;
|
pub use covariance::*;
|
||||||
|
|
||||||
#[cfg(feature = "parallel")]
|
|
||||||
use rayon::prelude::*;
|
|
||||||
|
|
||||||
pub fn mean(slice: &[f64]) -> f64
|
pub fn mean(slice: &[f64]) -> f64
|
||||||
{
|
{
|
||||||
slice
|
slice
|
||||||
// .par_iter()
|
|
||||||
.iter()
|
.iter()
|
||||||
.sum::<f64>() / slice.len() as f64
|
.sum::<f64>() / slice.len() as f64
|
||||||
}
|
}
|
||||||
@ -16,7 +12,6 @@ pub fn population_variance(slice: &[f64]) -> f64
|
|||||||
{
|
{
|
||||||
let mean = mean(slice);
|
let mean = mean(slice);
|
||||||
slice
|
slice
|
||||||
// .par_iter()
|
|
||||||
.iter()
|
.iter()
|
||||||
.map(|x| f64::powi(x - mean, 2))
|
.map(|x| f64::powi(x - mean, 2))
|
||||||
.sum::<f64>()
|
.sum::<f64>()
|
||||||
@ -27,7 +22,6 @@ pub fn sample_variance(slice: &[f64]) -> f64
|
|||||||
{
|
{
|
||||||
let mean = mean(slice);
|
let mean = mean(slice);
|
||||||
slice
|
slice
|
||||||
// .par_iter()
|
|
||||||
.iter()
|
.iter()
|
||||||
.map(|x| f64::powi(x - mean, 2))
|
.map(|x| f64::powi(x - mean, 2))
|
||||||
.sum::<f64>()
|
.sum::<f64>()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user