Skip to content

Commit

Permalink
Merge pull request #25 from primitivefinance/feat/vol-targeting
Browse files Browse the repository at this point in the history
Feat/Vol Targeting
  • Loading branch information
kinrezC authored Oct 11, 2023
2 parents 6a74d0c + 3946b59 commit 4d2cb48
Show file tree
Hide file tree
Showing 19 changed files with 1,178 additions and 237 deletions.
27 changes: 27 additions & 0 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: test

on: push

jobs:
test:
name: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3

- name: Install rust toolchain
uses: actions-rs/toolchain@v1
with:
toolchain: 1.71.0
override: true

- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1
with:
version: nightly

- name: Build bindings
run: FOUNDRY_PROFILE=default ./build.sh

- name: test
run: cargo test --workspace --exclude bindings
35 changes: 18 additions & 17 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ members = ["box-core", "box-simulation"]

[workspace.dependencies]
bindings = { path = "./box-contracts/out/bindings", version = "0.1.0" }
box_core = { path = "./box-core", version = "0.1.0" }
8 changes: 8 additions & 0 deletions box-contracts/src/AtomicArbitrage.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@ contract AtomicArbitrage {
address public asset;
address public quote;

constructor(address exchangeAddress, address liquidExchangeAddress, address assetAddress, address quoteAddress) {
exchange = exchangeAddress;
liquidExchange = liquidExchangeAddress;
asset = assetAddress;
quote = quoteAddress;
}


function lower_exchange_price(
uint256 input
) external {
Expand Down
2 changes: 1 addition & 1 deletion box-core/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[package]
name = "box-core"
name = "box_core"
version = "0.1.0"
edition = "2021"

Expand Down
123 changes: 94 additions & 29 deletions box-core/src/math.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,31 +11,68 @@ pub fn compute_returns(values: Vec<f64>) -> Vec<f64> {
returns
}

/// Computes the mean of a series of values (arithmetic average), finds the mean
/// of the summed differences of the values vs. the mean.
pub fn compute_variance(values: Vec<f64>) -> f64 {
let mean = values.iter().sum::<f64>() / values.len() as f64;
let variance = values
.iter()
.map(|&return_| (return_ - mean).powi(2))
.sum::<f64>()
/ values.len() as f64;
variance
pub trait ComputeReturns {
fn compute_log_returns(self) -> Vec<f64>;
fn compute_simple_returns(self) -> Vec<f64>;
fn compute_variance(self) -> f64;
fn compute_std_deviation(self) -> f64;
fn compute_realized_volatility(self) -> f64;
fn compute_sharpe_ratio(self) -> f64;
}

/// Computes the square root of the variance.
pub fn compute_std_deviation(values: Vec<f64>) -> f64 {
let variance = compute_variance(values);
variance.sqrt()
}

/// The sharpe ratio is the ratio of the mean of the returns to the standard
/// deviation of the returns.
pub fn compute_sharpe_ratio(values: Vec<f64>) -> f64 {
let returns = compute_returns(values);
let mean = returns.iter().sum::<f64>() / returns.len() as f64;
let std_deviation = compute_std_deviation(returns);
mean / std_deviation
impl<I> ComputeReturns for I
where
I: IntoIterator<Item = f64>,
{
fn compute_log_returns(self) -> Vec<f64> {
let mut previous_value = 0.0_f64;
let mut returns = Vec::new();
for value in self {
if previous_value != 0.0 {
returns.push((value / previous_value).ln());
}
previous_value = value;
}
returns
}
fn compute_simple_returns(self) -> Vec<f64> {
let mut previous_value = 0.0_f64;
let mut returns = Vec::new();
for value in self {
if previous_value != 0.0 {
returns.push(value / previous_value - 1.0);
}
previous_value = value;
}
returns
}
fn compute_variance(self) -> f64 {
let values = self.into_iter().collect::<Vec<f64>>();
let mean = values.iter().sum::<f64>() / values.len() as f64;
let variance = values
.iter()
.map(|&return_| (return_ - mean).powi(2))
.sum::<f64>()
/ values.len() as f64;
variance
}
fn compute_std_deviation(self) -> f64 {
let variance = self.compute_variance();
variance.sqrt()
}
fn compute_realized_volatility(self) -> f64 {
let returns = self.compute_log_returns();
let len = returns.len() + 1;
let rv = returns.compute_std_deviation() / (len as f64 / 365.0);
rv
}
// TODO: don't use log returns here, use simple returns
fn compute_sharpe_ratio(self) -> f64 {
let returns = self.compute_simple_returns();
let mean = returns.iter().sum::<f64>() / returns.len() as f64;
let std_deviation = returns.compute_std_deviation();
mean / std_deviation
}
}

/// Finds the volatility delta to match the target volatility, with respect to
Expand All @@ -56,30 +93,58 @@ pub fn compute_target_volatility_delta(
// todo: make sure these tests are correct, used copilot for them.
mod tests {
#[test]
fn test_compute_returns() {
fn test_compute_log_returns() {
use super::ComputeReturns;
let values = vec![1.0, 2.0, 3.0];
let returns = values.compute_log_returns();
assert_eq!(returns, [0.6931471805599453, 0.4054651081081644]);
}

#[test]
fn test_compute_simple_returns() {
use super::ComputeReturns;
let values = vec![1.0, 2.0, 3.0];
let returns = super::compute_returns(values);
assert_eq!(returns, vec![1.0, 0.5]);
let returns = values.compute_simple_returns();
assert_eq!(returns, [1.0, 0.5]);
}

#[test]
fn test_compute_variance() {
use super::ComputeReturns;
let values = vec![1.0, 2.0, 3.0];
let variance = super::compute_variance(values);
let variance = values.compute_variance();
assert_eq!(variance, 0.6666666666666666);
}

#[test]
fn test_compute_std_deviation() {
use super::ComputeReturns;
let values = vec![1.0, 2.0, 3.0];
let std_deviation = super::compute_std_deviation(values);
let std_deviation = values.compute_std_deviation();
assert_eq!(std_deviation, 0.816496580927726);
}

#[test]
fn test_std_dev_log_returns() {
use super::ComputeReturns;
let values = vec![1.0, 2.0, 3.0];
let vol = values.compute_log_returns().compute_std_deviation() / (3.0 / 365.0);
assert_eq!(vol, 17.50065940748334);
}

#[test]
fn test_realized_volatility() {
use super::ComputeReturns;
let values = vec![1.0, 2.0, 3.0];
let vol = values.compute_realized_volatility();
assert_eq!(vol, 17.50065940748334);
}

#[test]
fn test_compute_sharpe_ratio() {
use super::ComputeReturns;
let values = vec![1.0, 2.0, 3.0];
let sharpe_ratio = super::compute_sharpe_ratio(values);
let sharpe_ratio = values.compute_sharpe_ratio();
assert_eq!(sharpe_ratio, 3.0);
}
}
Loading

0 comments on commit 4d2cb48

Please sign in to comment.