Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 10 additions & 9 deletions doc/modules/ROOT/pages/examples.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@ https://www.boost.org/LICENSE_1_0.txt
= Examples
:idprefix: examples_

All examples can be found in the library `examples/` folder as well.
The following examples will help you get up and running with many of the major parts of the library.
All of these examples can be found in the library `examples/` folder as well.

[#examples_construction]
== Basic Construction
.This example demonstrates the basic use of the various constructors offered by the decimal types
.This https://github.com/cppalliance/decimal/blob/develop/examples/basic_construction.cpp[example] demonstrates the basic use of the various constructors offered by the decimal types
====
[source, c++]
----
Expand All @@ -35,7 +36,7 @@ Can not construct from invalid string
[#examples_promotion]
== Promotion and Mixed Decimal Arithmetic

.This example demonstrates the behaviors of promotion between types, and mixed decimal type arithmetic
.This https://github.com/cppalliance/decimal/blob/develop/examples/promotion.cpp[example] demonstrates the behaviors of promotion between types, and mixed decimal type arithmetic
====
[source, c++]
----
Expand All @@ -56,7 +57,7 @@ The result of a + b is a decimal64_t: 9.1
[#examples_charconv]
== `<charconv>`

.This example demonstrates the fundamentals of the `<charconv>` like functions provided by the library
.This https://github.com/cppalliance/decimal/blob/develop/examples/charconv.cpp[example] demonstrates the fundamentals of the `<charconv>` like functions provided by the library
====
[source, c++]
----
Expand All @@ -74,7 +75,7 @@ Value in scientific format with precision 20: -7.12345000000000000000e+06

[#examples_generic_programming]
== Generic Programming
.This example demonstrates how to write generic code that accepts both built-in floating point types, and decimal floating point values from this library
.This https://github.com/cppalliance/decimal/blob/develop/examples/adl.cpp[example] demonstrates how to write generic code that accepts both built-in floating point types, and decimal floating point values from this library
====
[source, c++]
----
Expand Down Expand Up @@ -111,7 +112,7 @@ sin(-0.5) = -0.479426

[#examples_literals_constants]
== Literals and Constants
.This example demonstrates how to construct values using literals, and the usage of numerical constants that are provided by the library
.This https://github.com/cppalliance/decimal/blob/develop/examples/literals.cpp[example] demonstrates how to construct values using literals, and the usage of numerical constants that are provided by the library
====
[source, c++]
----
Expand All @@ -138,7 +139,7 @@ pass:[{fmt}] support is available starting with pass:[C++14] so long as you have
[#examples_fmt_format]
=== `<fmt/format.hpp>`

.This example demonstrates the various formatting options provided by the library to support usage of pass:[{fmt}]
.This https://github.com/cppalliance/decimal/blob/develop/examples/fmt_format.cpp[example] demonstrates the various formatting options provided by the library to support usage of pass:[{fmt}]
====
[source, c++]
----
Expand Down Expand Up @@ -212,7 +213,7 @@ You must include it yourself.

Taking the above example of pass:[{fmt}] and replacing all instances of `namespace fmt` with `namespace std` gives us another working example.

.This example demonstrates how to use `<format>` with the library in-place or in addition to pass:[{fmt}]
.This https://github.com/cppalliance/decimal/blob/develop/examples/format.cpp[example] demonstrates how to use `<format>` with the library in-place or in addition to pass:[{fmt}]
====
[source, c++]
----
Expand Down Expand Up @@ -242,7 +243,7 @@ Scientific Format with Specified Precision and Padding:

[#examples_print]
=== `<print>`
.This example demonstrates how to use `<print>` with the library
.This https://github.com/cppalliance/decimal/blob/develop/examples/print.cpp[example] demonstrates how to use `<print>` with the library
====
[source, c++]
----
Expand Down
55 changes: 37 additions & 18 deletions doc/modules/ROOT/pages/financial_examples.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,42 @@ https://www.boost.org/LICENSE_1_0.txt
= Financial Examples
:idprefix: financial_examples_

== Financial Applications

=== Simple Moving Average

In the examples folder there is a file named `moving_average.cpp`.
This example shows how to parse historical stock data from a file and use it.
This serves as a framework for other calculations for securities.

=== Currency Conversion
In the examples folder there is a file named `currency_conversion.cpp`.
This example shows how to simply convert currencies based off a given exchange rate.
Below are a few additional examples as to how the Decimal library can be used in the context of financial applications.
All of these examples can be found in the library `examples/` folder as well.

== Parsing Pricing Data from File
[#examples_money_parsing]
.This https://github.com/cppalliance/decimal/blob/develop/examples/numerical_parsing.cpp[example] demonstrates the numerical differences between parsing of monetary values between using `decimal32_t` and `float`
====
[source, c++]
----
include::example$numerical_parsing.cpp[]
----

.Expected Output
....
Number of data points: 252
Sum from MS Excel: 52151.99
Sum using decimal32_t: 52151.99
Sum using float: 52151.96
....
====

[#examples_boost_math]
== Boost.Math Integration

=== Bollinger Bands

In the examples folder there is a file named `statistics.cpp`.
This example demonstrates how to parse a file, and then leverage Boost.Math to compute statistics of that data set culminating with the values of the Bollinger Bands.
This example could be extended with the simple moving average to create full bands based on the period of the moving average you would like.
== Boost.Math to Calculate Bollinger Bands
.This https://github.com/cppalliance/decimal/blob/develop/examples/statistics.cpp[example] demonstrates how we can use the decimal library with existing Boost.Math facilities to perform statistical analysis
====
[source, c++]
----
include::example$statistics.cpp[]
----

.Expected Output
....
Mean Closing Price: $207.20
Median Closing Price: $214.26
Standard Deviation: $25.45
Upper Bollinger Band: $258.11
Lower Bollinger Band: $156.30
....
====
28 changes: 0 additions & 28 deletions examples/currency_conversion.cpp

This file was deleted.

96 changes: 0 additions & 96 deletions examples/moving_average.cpp

This file was deleted.

106 changes: 106 additions & 0 deletions examples/numerical_parsing.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
// Copyright 2025 Matt Borland
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
//
// This file briefly demonstrates the difference in results when parsing monetary values between float and decimal32_t

#include "where_file.hpp"
#include <boost/decimal/decimal32_t.hpp> // For type decimal32_t
#include <boost/decimal/charconv.hpp> // For support to <charconv>
#include <boost/decimal/iostream.hpp> // For decimal support to <iostream>
#include <string>
#include <vector>
#include <fstream>
#include <sstream>
#include <limits>
#include <numeric>
#include <iostream>
#include <iomanip>

using boost::decimal::decimal32_t;

template <typename T>
T parse_opening_price(const std::string& line);

template <>
float parse_opening_price<float>(const std::string& line)
{
const auto result {std::stof(line)};
return result;
}

template <>
decimal32_t parse_opening_price<decimal32_t>(const std::string& line)
{
decimal32_t result;
const auto r = from_chars(line, result);

// If we have a parse failure throw std::invalid_argument if the environment supports it,
// using std::invalid_argument which is the same thing thrown by std::stof in the float case
//
// If we are in a no throw environment returning a qNaN will poison our results as well
if (!r)
{
// LCOV_EXCL_START
result = std::numeric_limits<decimal32_t>::quiet_NaN();
BOOST_DECIMAL_THROW_EXCEPTION(std::invalid_argument("Parsing has failed"));
// LCOV_EXCL_STOP
}

return result;
}

template <typename T>
T parse_csv_line(const std::string& line)
{
std::stringstream ss(line);
std::string token;
std::string date;

std::getline(ss, date, ',');
std::getline(ss, token, ',');

return parse_opening_price<T>(token);
}

int main()
{
// We have a CSV file containing one years worth of daily stock data for AAPL
// Here we will show the differences that arise (however small)
// between parsing with float and decimal32_t

// Open and read the CSV file
std::ifstream file(boost::decimal::where_file("AAPL.csv"));
std::string line;

// Skip header line
std::getline(file, line);

std::vector<decimal32_t> decimal_opening_prices;
std::vector<float> float_opening_prices;

// Parse each line once into decimal32_t and once into a float
while (std::getline(file, line))
{
decimal_opening_prices.emplace_back(parse_csv_line<decimal32_t>(line));
float_opening_prices.emplace_back(parse_csv_line<float>(line));
}

// Use std::accumulate to get the sum of all the pricing information in the array
// This will be used to compare the total value parsed
const auto decimal_sum {std::accumulate(decimal_opening_prices.begin(),
decimal_opening_prices.end(), decimal32_t{0})};

const auto float_sum {std::accumulate(float_opening_prices.begin(),
float_opening_prices.end(), float{0})};

// This is the reference value that was found using the sum command of the CSV
// inside Microsoft Excel
const std::string ms_excel_result {"52151.99"};

std::cout << std::setprecision(std::numeric_limits<float>::digits10 + 1)
<< "Number of data points: " << decimal_opening_prices.size() << '\n'
<< " Sum from MS Excel: " << ms_excel_result << '\n'
<< "Sum using decimal32_t: " << decimal_sum << '\n'
<< " Sum using float: " << float_sum << std::endl;
}
Loading
Loading