#include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>
#include <limits>
#include <chrono>
#include <thread>
#include <future>
#include <omp.h>
using namespace std;
double round_to(double value, double precision = 1.0)
{
return round(value / precision) * precision;
}
// Forward fill function to fill missing data points with the last valid value
void forward_fill(vector<double>& data) {
for (size_t i = 1; i < data.size(); ++i) {
// If the current value is zero (or NaN), replace it with the last valid value
if (data[i] == 0 || std::isnan(data[i])) {
data[i] = data[i - 1];
}
}
}
// Replace infinity values with a specified fallback value (e.g., 0 or last valid value)
void replace_infinity(vector<double>& data, double fallback_value = 90) {
for (size_t i = 1; i < data.size(); ++i) {
if (std::isinf(data[i])) {
// If the value is +∞ or -∞, replace it with fallback_value
if(data[i]<std::numeric_limits<int>::lowest())
data[i] = -fallback_value;
else
data[i] = fallback_value;
}
}
}
// Function to calculate Exponential Moving Average (EMA)
vector<double> ema(const vector<double>& data, size_t n) {
vector<double> result;
double multiplier = 2.0 / (n + 1);
// Initialize the first EMA value as the first data point
result.push_back(data[0]);
for (size_t i = 1; i < data.size(); ++i) {
result.push_back((data[i] - result[i - 1]) * multiplier + result[i - 1]);
}
return result;
}
// Function to calculate the rolling standard deviation (std)
vector<double> rolling_std(const vector<double>& data, size_t n) {
vector<double> result;
for (size_t i = 0; i < data.size(); ++i) {
if (i >= n - 1) {
double sum = 0, mean = 0, sq_sum = 0;
for (size_t j = i; j > i - n; --j) {
sum += data[j];
sq_sum += data[j] * data[j];
}
mean = sum / n;
result.push_back(sqrt(sq_sum / n - mean * mean));
}
}
return result;
}
// Function to calculate the Bollinger Bands and return the result as a vector
vector<double> bollinger(const vector<double>& data, const vector<double>& ema_data, const vector<double>& std_data, size_t n) {
vector<double> result(data.size(), 0);
vector<double> result_diff(data.size(), 0);
for (size_t i = 0; i < data.size(); ++i) {
if (i >= n - 1) {
result[i] = (data[i] - ema_data[i]) / std_data[i]; // Standardized difference
}
}
for (size_t i = 1; i < data.size(); ++i) {
result_diff[i] = round_to(result[i]-result[i-1], 0.000001); // Standardized difference
}
return result_diff;
}
void bollinger_exec(const vector<double>& data, const vector<double>& ema_data, const vector<double>& std_data, size_t n, vector<double>& result_diff) {
vector<double> result(data.size(), 0);
#pragma omp parallel num_threads(10)
{
#pragma omp parallel for num_threads(10)
for (size_t i = 0; i < data.size(); ++i) {
if (i >= n - 1) {
result[i] = (data[i] - ema_data[i]) / std_data[i]; // Standardized difference
}
}
}
result_diff.emplace_back(0);
for (size_t i = 1; i < data.size(); ++i)
{
//result_diff[i] = round_to(result[i]-result[i-1], 0.000001); // Standardized difference
result_diff.emplace_back(round_to(result[i]-result[i-1], 0.000001));
}
}
// Function to transform data (calculate EMA, std, Bollinger) and apply forward fill and infinity replacement
vector<vector<double>> transform(const vector<double>& data, size_t n) {
// Calculate EMA
vector<double> bollinger_data;
vector<double> ema_data;
vector<double> std_data;
ema_data = ema(data, n);
// Calculate rolling standard deviation
std_data = rolling_std(data, n);
// Calculate Bollinger Bands
//future<vector<double>> ema_async = async(launch::deferred, ema, ref(data), n);
//future<vector<double>> std_async = async(launch::deferred, rolling_std, ref(data), n);
//vector<double> ema_data = ema_async.get();
//vector<double> std_data = std_async.get();
//vector<double> bollinger_data = bollinger(data, ema_data, std_data, n);
bollinger_exec(data, ema_data, std_data, n, bollinger_data);
//future<void> boll_async = async(launch::deferred,bollinger_exec, ref(data), ref(ema_data), ref(std_data), n,ref(bollinger_data));
//boll_async.wait();
//thread t = thread(bollinger_exec, ref(data), ref(ema_data), ref(std_data), n, ref(bollinger_data));
//t.join();
// Forward fill the Bollinger Bands, EMA, and std data to handle any missing values
//forward_fill(ema_data);
//forward_fill(std_data);
forward_fill(bollinger_data);
//thread t_forward_fill = thread(forward_fill, ref(bollinger_data));
//thread t_replace_infinity = thread(replace_infinity, ref(bollinger_data), n);
// Replace infinity values with fallback_value (0 for simplicity)
//replace_infinity(ema_data);
//replace_infinity(std_data);
replace_infinity(bollinger_data);
//t_forward_fill.join();
//t_replace_infinity.join();
//future<void> t_forward_fill = async(launch::deferred,forward_fill, ref(bollinger_data));
//t_forward_fill.wait();
//future<void> t_replace_infinity = async(launch::deferred, replace_infinity, ref(bollinger_data), n);
//t_replace_infinity.wait();
// Combine the results into a 2D vector (for simplicity)
//vector<vector<double>> result;
vector<vector<double>> result(data.size(), vector<double>(4, 0));
for (size_t i = 0; i < data.size(); ++i) {
result[i][0] = data[i]; // Original Data
result[i][1] = ema_data[i]; // EMA
result[i][2] = std_data[i]; // Rolling STD
result[i][3] = bollinger_data[i]; // Bollinger Bands
}
return result;
}
int main() {
// Sample data (example: closing prices)
//vector<double> data = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0};
// Introduce some infinity values for testing
//data[3] = std::numeric_limits<double>::infinity(); // +∞ at index 3
//data[5] = -std::numeric_limits<double>::infinity(); // -∞ at index 5
for (size_t i = 0; i < 100; i++)
{
size_t n = 3; // Period for EMA and Bollinger
//replace_infinity(data);
// Call the transform function
auto t1 = chrono::high_resolution_clock::now();
vector<double> data;
for (size_t i = 1; i <= 50; i++)
{
double ii(i);
data.emplace_back(ii);
}
vector<vector<double>> result = transform(data, n);
auto t2 = chrono::high_resolution_clock::now();
chrono::duration<double, std::milli> ms_double = t2 - t1;
std::cout << ms_double.count() << "ms\n"<<endl;
std::cout << result.size() <<"n"<<endl;
// Output the results
/*for (size_t i = n+1; i < result.size(); ++i) {
cout << "Data: " << result[i][0]
<< " EMA: " << result[i][1]
<< " Std: " << result[i][2]
<< " Bollinger: " << result[i][3] << endl;
}*/
}
system("pause");
return 0;
}