-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
bb21c75
commit 1eed83b
Showing
42 changed files
with
3,561 additions
and
23 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
// For format details, see https://aka.ms/devcontainer.json. For config options, see the | ||
// README at: https://github.com/devcontainers/templates/tree/main/src/rust | ||
{ | ||
"name": "Rust", | ||
// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile | ||
"image": "mcr.microsoft.com/devcontainers/rust:1-1-bullseye" | ||
|
||
// Use 'mounts' to make the cargo cache persistent in a Docker Volume. | ||
// "mounts": [ | ||
// { | ||
// "source": "devcontainer-cargo-cache-${devcontainerId}", | ||
// "target": "/usr/local/cargo", | ||
// "type": "volume" | ||
// } | ||
// ] | ||
|
||
// Features to add to the dev container. More info: https://containers.dev/features. | ||
// "features": {}, | ||
|
||
// Use 'forwardPorts' to make a list of ports inside the container available locally. | ||
// "forwardPorts": [], | ||
|
||
// Use 'postCreateCommand' to run commands after the container is created. | ||
// "postCreateCommand": "rustc --version", | ||
|
||
// Configure tool-specific properties. | ||
// "customizations": {}, | ||
|
||
// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. | ||
// "remoteUser": "root" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
# To get started with Dependabot version updates, you'll need to specify which | ||
# package ecosystems to update and where the package manifests are located. | ||
# Please see the documentation for more information: | ||
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates | ||
# https://containers.dev/guide/dependabot | ||
|
||
version: 2 | ||
updates: | ||
- package-ecosystem: "devcontainers" | ||
directory: "/" | ||
schedule: | ||
interval: weekly |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,9 @@ | ||
target | ||
target_ci | ||
target_ci_stable | ||
Cargo.lock | ||
third_party | ||
/Cargo.toml | ||
out/ | ||
|
||
.idea | ||
.vscode | ||
# .vscode |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
{ | ||
// Use IntelliSense to learn about possible attributes. | ||
// Hover to view descriptions of existing attributes. | ||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 | ||
"version": "0.2.0", | ||
"configurations": [ | ||
{ | ||
"type": "lldb", | ||
"request": "launch", | ||
"name": "Cargo test", | ||
"cargo": { | ||
"args": [ | ||
"test", | ||
"--no-run", | ||
"--lib" | ||
] | ||
}, | ||
"args": [] | ||
} | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
{ | ||
"editor.formatOnSave": true, | ||
"files.autoSave": "onFocusChange", | ||
"editor.defaultFormatter": "rust-lang.rust-analyzer" | ||
} |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
[package] | ||
name = "trading-lib" | ||
version = "0.1.0" | ||
edition = "2021" | ||
|
||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||
|
||
[dependencies] | ||
anyhow = "1.0.86" | ||
rust_decimal = "1.35.0" | ||
thiserror = "1.0.62" | ||
|
||
[dependencies.xrpl-rust] | ||
git = "https://github.com/sephynox/xrpl-rust.git" | ||
branch = "dev" | ||
optional = true | ||
|
||
[dev-dependencies] | ||
rand = "0.8.5" | ||
|
||
[features] | ||
default = ["arbitrage", "market-maker", "xrpl"] | ||
xrpl = ["xrpl-rust", "automated-market-maker"] | ||
arbitrage = [] | ||
market-maker = [] | ||
automated-market-maker = [] | ||
|
||
[[test]] | ||
name = "unit_tests" | ||
path = "tests/unit/mod.rs" |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
A library providing utilities for arbitrage trading and market making on the XRPL. | ||
A library providing utilities for arbitrage trading and market making. |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
pub mod models; | ||
pub mod order_books; | ||
pub mod trading_types; | ||
pub mod utils; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
use std::borrow::Cow; | ||
|
||
extern crate xrpl; | ||
|
||
use xrpl::models::amount::{Amount, IssuedCurrencyAmount, XRPAmount}; | ||
#[cfg(feature = "xrpl")] | ||
use xrpl::models::currency::Currency as XRPLCurrency; | ||
|
||
#[derive(Debug, Clone, PartialEq)] | ||
pub struct Currency<'a> { | ||
pub currency_code: Cow<'a, str>, | ||
pub issuer: Cow<'a, str>, | ||
pub transfer_fee: f32, | ||
} | ||
|
||
#[cfg(feature = "xrpl")] | ||
impl<'a> Currency<'a> { | ||
pub fn get_xrpl_amount(&self, amount: Cow<'a, str>) -> Amount<'a> { | ||
match self.currency_code.as_ref() { | ||
"XRP" => XRPAmount(amount).into(), | ||
_ => IssuedCurrencyAmount::new(self.currency_code.clone(), self.issuer.clone(), amount) | ||
.into(), | ||
} | ||
} | ||
} | ||
|
||
#[cfg(feature = "xrpl")] | ||
impl<'a> Currency<'a> { | ||
pub fn from_xrpl(currency: XRPLCurrency<'a>, transfer_fee: Option<f32>) -> Self { | ||
match currency { | ||
XRPLCurrency::XRP(_) => Self { | ||
currency_code: "XRP".into(), | ||
issuer: "".into(), | ||
transfer_fee: 0.0, | ||
}, | ||
XRPLCurrency::IssuedCurrency(issued_currency) => Self { | ||
currency_code: issued_currency.currency, | ||
issuer: issued_currency.issuer, | ||
transfer_fee: transfer_fee.unwrap_or(0.0), | ||
}, | ||
} | ||
} | ||
} | ||
|
||
impl Currency<'_> { | ||
pub fn is_same_currency(&self, other: &Self) -> bool { | ||
self.currency_code == other.currency_code | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
pub mod currency; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
use thiserror::Error; | ||
|
||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Error)] | ||
pub enum OrderBookException { | ||
#[error("Invalid order")] | ||
InvalidOrder, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
pub mod exceptions; | ||
pub mod order; | ||
pub mod order_book; | ||
|
||
use order_book::OrderBook; | ||
|
||
#[derive(Debug)] | ||
pub struct OrderBooks<'a> { | ||
pub order_books: Vec<OrderBook<'a>>, | ||
pub liquidity_spread: f64, | ||
} | ||
|
||
impl<'a> OrderBooks<'a> { | ||
pub fn sort(&mut self) { | ||
self.order_books | ||
.iter_mut() | ||
.for_each(|order_book| order_book.sort()); | ||
} | ||
} | ||
|
||
pub trait IsLiquid { | ||
/// Returns true if the order book is liquid determained based on the provided `liquidity_spread`. | ||
fn is_liquid(&self, liquidity_spread: f64) -> bool; | ||
} | ||
|
||
pub trait Flip { | ||
fn flip(&mut self); | ||
|
||
fn get_flipped(&self) -> Self | ||
where | ||
Self: Sized + Clone, | ||
{ | ||
let mut flipped = self.clone(); | ||
flipped.flip(); | ||
|
||
flipped | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,164 @@ | ||
use std::{cmp::Ordering, mem::swap}; | ||
|
||
use rust_decimal::{prelude::FromPrimitive, Decimal}; | ||
#[cfg(feature = "xrpl")] | ||
use xrpl::models::{ | ||
amount::Amount, | ||
currency::{Currency as XRPLCurrency, IssuedCurrency, XRP}, | ||
ledger::Offer, | ||
transactions::{OfferCreate, OfferCreateFlag}, | ||
FlagCollection, | ||
}; | ||
|
||
use crate::models::currency::Currency; | ||
|
||
use super::Flip; | ||
|
||
#[derive(Debug, Clone)] | ||
pub struct Order<'a> { | ||
pub base: Currency<'a>, | ||
pub counter: Currency<'a>, | ||
pub base_quantity: Decimal, | ||
pub rate: Decimal, | ||
} | ||
|
||
impl Flip for Order<'_> { | ||
fn flip(&mut self) { | ||
self.rate = Decimal::from(1) / self.rate; | ||
self.base_quantity = self.base_quantity * self.rate; | ||
swap(&mut self.base, &mut self.counter); | ||
} | ||
} | ||
|
||
impl PartialEq for Order<'_> { | ||
fn eq(&self, other: &Self) -> bool { | ||
self.rate == other.rate | ||
} | ||
} | ||
|
||
impl Eq for Order<'_> {} | ||
|
||
impl PartialOrd for Order<'_> { | ||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> { | ||
self.rate.partial_cmp(&other.rate) | ||
} | ||
} | ||
|
||
impl Ord for Order<'_> { | ||
fn cmp(&self, other: &Self) -> Ordering { | ||
self.rate.cmp(&other.rate) | ||
} | ||
} | ||
|
||
impl Order<'_> { | ||
pub fn calculate_counter_quantity_after_fee(&self) -> Decimal { | ||
(self.base_quantity * self.rate) | ||
* Decimal::from_f32(1.0 - self.counter.transfer_fee).unwrap() | ||
} | ||
} | ||
|
||
#[cfg(feature = "xrpl")] | ||
impl<'a> From<Offer<'a>> for Order<'a> { | ||
fn from(offer: Offer<'a>) -> Self { | ||
let (taker_gets_currency, taker_gets_amount): (XRPLCurrency, String) = | ||
match offer.taker_gets { | ||
Amount::XRPAmount(xrp) => (XRP::new().into(), xrp.0.into()), | ||
Amount::IssuedCurrencyAmount(issued_currency) => ( | ||
IssuedCurrency::new(issued_currency.currency, issued_currency.issuer).into(), | ||
issued_currency.value.into(), | ||
), | ||
}; | ||
let (taker_pays_currency, taker_pays_amount): (XRPLCurrency, String) = | ||
match offer.taker_pays { | ||
Amount::XRPAmount(xrp) => (XRP::new().into(), xrp.0.into()), | ||
Amount::IssuedCurrencyAmount(issued_currency) => ( | ||
IssuedCurrency::new(issued_currency.currency, issued_currency.issuer).into(), | ||
issued_currency.value.into(), | ||
), | ||
}; | ||
let taker_gets_amount: Decimal = taker_gets_amount.parse().unwrap(); | ||
let taker_pays_amount: Decimal = taker_pays_amount.parse().unwrap(); | ||
|
||
Self { | ||
base: Currency::from_xrpl(taker_pays_currency, None), | ||
counter: Currency::from_xrpl(taker_gets_currency, None), | ||
base_quantity: taker_pays_amount, | ||
rate: taker_gets_amount / taker_pays_amount, | ||
} | ||
} | ||
} | ||
|
||
#[cfg(feature = "xrpl")] | ||
impl<'a> Into<OfferCreate<'a>> for Order<'a> { | ||
fn into(self) -> OfferCreate<'a> { | ||
let base_qty = self.base_quantity.to_string(); | ||
let counter_qty = self.calculate_counter_quantity_after_fee().to_string(); | ||
|
||
OfferCreate::new( | ||
"".into(), | ||
None, | ||
None, | ||
Some(FlagCollection::new(vec![ | ||
OfferCreateFlag::TfImmediateOrCancel, | ||
OfferCreateFlag::TfSell, | ||
])), | ||
None, | ||
None, | ||
None, | ||
None, | ||
None, | ||
None, | ||
self.counter.get_xrpl_amount(counter_qty.into()), | ||
self.base.get_xrpl_amount(base_qty.into()), | ||
None, | ||
None, | ||
) | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod order_tests { | ||
use rust_decimal::{prelude::FromPrimitive, Decimal}; | ||
use xrpl::models::{ | ||
amount::{IssuedCurrencyAmount, XRPAmount}, | ||
FlagCollection, | ||
}; | ||
|
||
use super::*; | ||
|
||
#[test] | ||
#[cfg(feature = "xrpl")] | ||
fn test_from_offer() { | ||
let offer = Offer::new( | ||
FlagCollection::new(Vec::new()), | ||
None, | ||
None, | ||
"r".into(), | ||
"1".into(), | ||
"10".into(), | ||
"".into(), | ||
"".into(), | ||
0, | ||
0, | ||
IssuedCurrencyAmount::new("USD".into(), "issuer".into(), "10".into()).into(), | ||
XRPAmount("20".into()).into(), | ||
None, | ||
); | ||
let order = Order::from(offer); | ||
assert_eq!( | ||
order, | ||
Order { | ||
base: Currency::from_xrpl(XRPLCurrency::XRP(XRP::new()), None), | ||
counter: Currency::from_xrpl( | ||
XRPLCurrency::IssuedCurrency(IssuedCurrency::new( | ||
"USD".into(), | ||
"issuer".into() | ||
)), | ||
None | ||
), | ||
base_quantity: Decimal::from(20), | ||
rate: Decimal::from_f32(0.5).unwrap(), | ||
} | ||
); | ||
} | ||
} |
Oops, something went wrong.