diff --git a/FinLib.NET/FinLib/FinLib.Indicators.cs b/FinLib.NET/FinLib/FinLib.Indicators.cs new file mode 100644 index 0000000..ff196c0 --- /dev/null +++ b/FinLib.NET/FinLib/FinLib.Indicators.cs @@ -0,0 +1,7 @@ +namespace FinLib; + +public static class Indicators +{ + public static double RelativeStrengthIndicator(double timePeriod, double averageGain, double averageLoss) => NativeMethods.relative_strength_indicator(timePeriod, averageGain, averageLoss); + public static double RelativeStrengthIndicatorSmoothed(double timePeriod, double previousAverageGain, double currentGain, double previousAverageLoss, double currentLoss) => NativeMethods.relative_strength_indicator_smoothed(timePeriod, previousAverageGain, currentGain, previousAverageLoss, currentLoss); +} \ No newline at end of file diff --git a/FinLib.NET/FinLib/NativeMethods.g.cs b/FinLib.NET/FinLib/NativeMethods.g.cs index 07f8c5b..247a555 100644 --- a/FinLib.NET/FinLib/NativeMethods.g.cs +++ b/FinLib.NET/FinLib/NativeMethods.g.cs @@ -76,6 +76,12 @@ namespace FinLib [DllImport(__DllName, EntryPoint = "portfolio_value_at_risk_percent", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] internal static extern NullableFloat portfolio_value_at_risk_percent(Portfolio_native* portfolio, double confidence); + [DllImport(__DllName, EntryPoint = "relative_strength_indicator", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + internal static extern double relative_strength_indicator(double time_period, double average_gain, double average_loss); + + [DllImport(__DllName, EntryPoint = "relative_strength_indicator_smoothed", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + internal static extern double relative_strength_indicator_smoothed(double time_period, double previous_average_gain, double current_gain, double previous_average_loss, double current_loss); + } diff --git a/finlib-cpp/CMakeLists.txt b/finlib-cpp/CMakeLists.txt index e013ffc..cc1bce3 100644 --- a/finlib-cpp/CMakeLists.txt +++ b/finlib-cpp/CMakeLists.txt @@ -11,6 +11,7 @@ project(finlib-cpp) set(CMAKE_CXX_STANDARD 23) +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) set(CMAKE_INSTALL_PREFIX ${PROJECT_SOURCE_DIR}) set(FINLIB_INSTALL_INCLUDE_DIR ${PROJECT_SOURCE_DIR}/include) diff --git a/finlib-cpp/include/finlib/finlib-native.h b/finlib-cpp/include/finlib/finlib-native.h index 4358da3..ddf760d 100644 --- a/finlib-cpp/include/finlib/finlib-native.h +++ b/finlib-cpp/include/finlib/finlib-native.h @@ -76,6 +76,14 @@ NullableFloat portfolio_value_at_risk(Portfolio *portfolio, NullableFloat portfolio_value_at_risk_percent(Portfolio *portfolio, double confidence); +double relative_strength_indicator(double time_period, double average_gain, double average_loss); + +double relative_strength_indicator_smoothed(double time_period, + double previous_average_gain, + double current_gain, + double previous_average_loss, + double current_loss); + double scale_value_at_risk(double initial_value, ptrdiff_t time_cycles); NullableFloat varcovar_value_at_risk(const double *arr, size_t len, double confidence); diff --git a/finlib-cpp/src/CMakeLists.txt b/finlib-cpp/src/CMakeLists.txt index cbfe99f..622186c 100644 --- a/finlib-cpp/src/CMakeLists.txt +++ b/finlib-cpp/src/CMakeLists.txt @@ -2,7 +2,8 @@ cmake_minimum_required(VERSION 3.19) project(finexe) add_subdirectory(finlib) -set(SOURCE_FILES main.cpp +set(SOURCE_FILES + main.cpp ) add_executable(finexe ${SOURCE_FILES}) diff --git a/finlib-cpp/src/finlib/CMakeLists.txt b/finlib-cpp/src/finlib/CMakeLists.txt index cbf731b..168329f 100644 --- a/finlib-cpp/src/finlib/CMakeLists.txt +++ b/finlib-cpp/src/finlib/CMakeLists.txt @@ -7,6 +7,7 @@ set(SOURCE_FILES ) add_library(finlib SHARED STATIC ${SOURCE_FILES}) +add_library(finlib::finlib ALIAS finlib) ExternalProject_Add( finlibrs @@ -25,4 +26,4 @@ target_link_libraries(finlib ) install(TARGETS finlib DESTINATION ${FINLIB_INSTALL_LIB_DIR}) -install(FILES finlib.h DESTINATION ${FINLIB_INSTALL_INCLUDE_DIR}) \ No newline at end of file +install(FILES finlib.hpp DESTINATION ${FINLIB_INSTALL_INCLUDE_DIR}) diff --git a/finlib-ffi/build.rs b/finlib-ffi/build.rs index 3eff927..ada66eb 100644 --- a/finlib-ffi/build.rs +++ b/finlib-ffi/build.rs @@ -19,6 +19,7 @@ fn main() { csbindgen::Builder::default() .input_extern_file("src/lib.rs") .input_extern_file("src/portfolio.rs") + .input_extern_file("src/indicators.rs") .input_extern_file("../finlib/src/risk/portfolio.rs") .csharp_dll_name("libfinlib_ffi") .csharp_namespace("FinLib") diff --git a/finlib-ffi/src/indicators.rs b/finlib-ffi/src/indicators.rs new file mode 100644 index 0000000..4a80b83 --- /dev/null +++ b/finlib-ffi/src/indicators.rs @@ -0,0 +1,10 @@ + +#[no_mangle] +pub extern "C" fn relative_strength_indicator(time_period: f64, average_gain: f64, average_loss: f64) -> f64 { + finlib::indicators::rsi::relative_strength_indicator(time_period, average_gain, average_loss) +} + +#[no_mangle] +pub extern "C" fn relative_strength_indicator_smoothed(time_period: f64, previous_average_gain: f64, current_gain: f64, previous_average_loss: f64, current_loss: f64) -> f64 { + finlib::indicators::rsi::relative_strength_indicator_smoothed(time_period, previous_average_gain, current_gain, previous_average_loss, current_loss) +} \ No newline at end of file diff --git a/finlib-ffi/src/lib.rs b/finlib-ffi/src/lib.rs index fb4f934..811c091 100644 --- a/finlib-ffi/src/lib.rs +++ b/finlib-ffi/src/lib.rs @@ -1,4 +1,5 @@ -mod portfolio; +pub mod portfolio; +pub mod indicators; use std::slice; diff --git a/finlib-wasm/src/lib.rs b/finlib-wasm/src/lib.rs index 109bffb..11d0ae7 100644 --- a/finlib-wasm/src/lib.rs +++ b/finlib-wasm/src/lib.rs @@ -14,6 +14,21 @@ pub fn init_logging() { } } +#[wasm_bindgen] +pub struct RelativeStrengthIndicator { } + +#[wasm_bindgen] +impl RelativeStrengthIndicator { + pub fn relative_strength_indicator(time_period: f64, average_gain: f64, average_loss: f64) -> f64 { + finlib::indicators::rsi::relative_strength_indicator(time_period, average_gain, average_loss) + } + + pub fn relative_strength_indicator_smoothed(time_period: f64, previous_average_gain: f64, current_gain: f64, previous_average_loss: f64, current_loss: f64) -> f64 { + finlib::indicators::rsi::relative_strength_indicator_smoothed(time_period, previous_average_gain, current_gain, previous_average_loss, current_loss) + } +} + + #[wasm_bindgen] pub struct Interest { } diff --git a/finlib/src/indicators/mod.rs b/finlib/src/indicators/mod.rs new file mode 100644 index 0000000..1481c55 --- /dev/null +++ b/finlib/src/indicators/mod.rs @@ -0,0 +1 @@ +pub mod rsi; \ No newline at end of file diff --git a/finlib/src/indicators/rsi/mod.rs b/finlib/src/indicators/rsi/mod.rs new file mode 100644 index 0000000..eb2a8c4 --- /dev/null +++ b/finlib/src/indicators/rsi/mod.rs @@ -0,0 +1,38 @@ + + +pub fn relative_strength_indicator(time_period: f64, average_gain: f64, average_loss: f64) -> f64 { + 100. - ( + 100. / + (1. + ( + (average_gain / time_period) + / + (average_loss / time_period) + ) + ) + ) +} + +pub fn relative_strength_indicator_smoothed(time_period: f64, previous_average_gain: f64, current_gain: f64, previous_average_loss: f64, current_loss: f64) -> f64 { + 100. - (100. / + (1. + + ( + ((previous_average_gain * time_period) + current_gain) + + / + + ((previous_average_loss * time_period) + current_loss) + ) + ) + ) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn relative_strength_indicator_test() { + let result = relative_strength_indicator(14., 1., 0.8); + assert_eq!(f64::floor(result * 100.) / 100., 55.55); + } +} diff --git a/finlib/src/lib.rs b/finlib/src/lib.rs index 1e01328..e4b4544 100644 --- a/finlib/src/lib.rs +++ b/finlib/src/lib.rs @@ -5,4 +5,5 @@ pub mod stats; pub mod util; pub mod risk; pub mod ffi; -pub mod options; \ No newline at end of file +pub mod options; +pub mod indicators; \ No newline at end of file diff --git a/pyfinlib/src/lib.rs b/pyfinlib/src/lib.rs index 285e481..a6ce2fc 100644 --- a/pyfinlib/src/lib.rs +++ b/pyfinlib/src/lib.rs @@ -15,6 +15,26 @@ mod pyfinlib { Ok(()) } + #[pymodule] + mod indicators { + use super::*; + + #[pymodule] + mod rsi { + use super::*; + + #[pyfunction] + pub fn relative_strength_indicator(time_period: f64, average_gain: f64, average_loss: f64) -> PyResult<f64> { + Ok(finlib::indicators::rsi::relative_strength_indicator(time_period, average_gain, average_loss)) + } + + #[pyfunction] + pub fn relative_strength_indicator_smoothed(time_period: f64, previous_average_gain: f64, current_gain: f64, previous_average_loss: f64, current_loss: f64) -> PyResult<f64> { + Ok(finlib::indicators::rsi::relative_strength_indicator_smoothed(time_period, previous_average_gain, current_gain, previous_average_loss, current_loss)) + } + } + } + #[pymodule] mod interest { use super::*;