CcyConv.jl
CcyConv is a Julia package for performing currency conversions. It allows for direct and multi-step conversions using the latest exchange 💱 rates.
Installation
If you haven't installed our local registry yet, do that first:
] registry add https://github.com/bhftbootcamp/Green.gitTo install CcyConv, simply use the Julia package manager:
] add CcyConvUsage
Here's how you can find a conversion path from ADA to BNB:
graph LR;
ADA --> |0.5911| USDT;
ADA -.->|0.00000892| BTC;
BTC -.->|19.9089| ETH;
USDT --> |0.0003| ETH;
ETH --> |5.9404| BNB;
USDT -.->|1.6929| XRP;
XRP -.- |NaN| BNB;
USDC -.- |1.6920| XRP;
ADA -.- |0.5909| USDC;
classDef julia_blue fill:#4063D8,stroke:#333,stroke-width:2px;
classDef julia_green fill:#389826,stroke:#333,stroke-width:2px;
classDef julia_red fill:#CB3C33,stroke:#333,stroke-width:2px;
classDef julia_purple fill:#9558B2,stroke:#333,stroke-width:2px;
classDef def_color fill:#eee,stroke:#ccc,stroke-width:2px;
class ADA julia_blue;
class USDT julia_red;
class ETH julia_green;
class BNB julia_purple;
using CcyConv
crypto = FXGraph()
append!(
crypto,
[
Price("ADA", "USDT", 0.5911),
Price("ADA", "BTC", 0.00000892),
Price("BTC", "ETH", 19.9089),
Price("USDT", "ETH", 0.0003),
Price("ETH", "BNB", 5.9404),
Price("USDT", "XRP", 1.6929),
Price("XRP", "BNB", NaN),
Price("USDC", "XRP", 1.6920),
Price("ADA", "USDC", 0.5909),
],
)
result = conv(crypto, "ADA", "BNB")
julia> conv_value(result)
0.0010534111319999999
julia> conv_chain(result)
3-element Vector{CcyConv.AbstractPrice}:
Price("ADA", "USDT", 0.5911)
Price("USDT", "ETH", 0.0003)
Price("ETH", "BNB", 5.9404)The graph topology can be built upfront — without actual prices — and the rates resolved lazily at query time through a custom context. This lets you fetch and cache live data from any source on the fly.
using CcyConv
using EasyCurl
using Serde
struct BinanceCtx <: CcyConv.AbstractCtx
prices::Dict{String,Float64}
BinanceCtx() = new(Dict{String,Float64}())
end
struct BinancePair <: CcyConv.AbstractPrice
base_asset::String
quote_asset::String
symbol::String
end
CcyConv.from_asset(x::BinancePair) = x.base_asset
CcyConv.to_asset(x::BinancePair) = x.quote_asset
function CcyConv.price(ctx::BinanceCtx, x::BinancePair)::Float64
return get!(ctx.prices, x.symbol) do
try
resp = http_get("https://api.binance.com/api/v3/avgPrice?symbol=$(x.symbol)")
data = Serde.parse_json(http_body(resp))
parse(Float64, data["price"])
catch
NaN
end
end
end
fx = FXGraph()
ctx = BinanceCtx()
append!(
fx,
[
BinancePair("ADA", "BTC", "ADABTC"),
BinancePair("BTC", "USDT", "BTCUSDT"),
BinancePair("PEPE", "USDT", "PEPEUSDT"),
BinancePair("EOS", "USDT", "EOSUSDT"),
],
)
# First call fetches prices from the exchange
julia> @time conv(fx, "ADA", "EOS"; ctx = ctx) |> conv_value
0.350000 seconds (...)
0.6004274502578457
# Subsequent calls use cached prices
julia> @time conv(fx, "ADA", "EOS"; ctx = ctx) |> conv_value
0.000130 seconds (46 allocations: 2.312 KiB)
0.6004274502578457