mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-06-11 07:23:32 -07:00
investing: more data + charts
This commit is contained in:
Generated
-6
@@ -2433,8 +2433,6 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "rawdb"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39ebb540a243e937d5ec268361bbf7b83e05e6c4ad8de21ac9ee64c4f72e9001"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
@@ -3253,8 +3251,6 @@ checksum = "8f54a172d0620933a27a4360d3db3e2ae0dd6cceae9730751a036bbf182c4b23"
|
||||
[[package]]
|
||||
name = "vecdb"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d64486e34d56d63797295aa928288542226b6f28f96a3b58f661b1efd9f54cde"
|
||||
dependencies = [
|
||||
"ctrlc",
|
||||
"log",
|
||||
@@ -3274,8 +3270,6 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "vecdb_derive"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c1f863f6687e9ff90962a51a0f6c9646a14dc0ccfd9ea2ea79e288d88187bef"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn",
|
||||
|
||||
+2
-2
@@ -82,8 +82,8 @@ tokio = { version = "1.49.0", features = ["rt-multi-thread"] }
|
||||
tracing = { version = "0.1", default-features = false, features = ["std"] }
|
||||
tower-http = { version = "0.6.8", features = ["catch-panic", "compression-br", "compression-gzip", "compression-zstd", "cors", "normalize-path", "timeout", "trace"] }
|
||||
tower-layer = "0.3"
|
||||
vecdb = { version = "0.6.1", features = ["derive", "serde_json", "pco", "schemars"] }
|
||||
# vecdb = { path = "../anydb/crates/vecdb", features = ["derive", "serde_json", "pco", "schemars"] }
|
||||
# vecdb = { version = "0.6.1", features = ["derive", "serde_json", "pco", "schemars"] }
|
||||
vecdb = { path = "../anydb/crates/vecdb", features = ["derive", "serde_json", "pco", "schemars"] }
|
||||
|
||||
[workspace.metadata.release]
|
||||
shared-version = true
|
||||
|
||||
+336
-170
@@ -1532,42 +1532,6 @@ impl PeriodLumpSumStackPattern {
|
||||
}
|
||||
}
|
||||
|
||||
/// Pattern struct for repeated tree structure.
|
||||
pub struct PeriodAveragePricePattern<T> {
|
||||
pub _10y: MetricPattern4<T>,
|
||||
pub _1m: MetricPattern4<T>,
|
||||
pub _1w: MetricPattern4<T>,
|
||||
pub _1y: MetricPattern4<T>,
|
||||
pub _2y: MetricPattern4<T>,
|
||||
pub _3m: MetricPattern4<T>,
|
||||
pub _3y: MetricPattern4<T>,
|
||||
pub _4y: MetricPattern4<T>,
|
||||
pub _5y: MetricPattern4<T>,
|
||||
pub _6m: MetricPattern4<T>,
|
||||
pub _6y: MetricPattern4<T>,
|
||||
pub _8y: MetricPattern4<T>,
|
||||
}
|
||||
|
||||
impl<T: DeserializeOwned> PeriodAveragePricePattern<T> {
|
||||
/// Create a new pattern node with accumulated metric name.
|
||||
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
|
||||
Self {
|
||||
_10y: MetricPattern4::new(client.clone(), _p("10y", &acc)),
|
||||
_1m: MetricPattern4::new(client.clone(), _p("1m", &acc)),
|
||||
_1w: MetricPattern4::new(client.clone(), _p("1w", &acc)),
|
||||
_1y: MetricPattern4::new(client.clone(), _p("1y", &acc)),
|
||||
_2y: MetricPattern4::new(client.clone(), _p("2y", &acc)),
|
||||
_3m: MetricPattern4::new(client.clone(), _p("3m", &acc)),
|
||||
_3y: MetricPattern4::new(client.clone(), _p("3y", &acc)),
|
||||
_4y: MetricPattern4::new(client.clone(), _p("4y", &acc)),
|
||||
_5y: MetricPattern4::new(client.clone(), _p("5y", &acc)),
|
||||
_6m: MetricPattern4::new(client.clone(), _p("6m", &acc)),
|
||||
_6y: MetricPattern4::new(client.clone(), _p("6y", &acc)),
|
||||
_8y: MetricPattern4::new(client.clone(), _p("8y", &acc)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Pattern struct for repeated tree structure.
|
||||
pub struct ClassAveragePricePattern<T> {
|
||||
pub _2015: MetricPattern4<T>,
|
||||
@@ -1604,6 +1568,42 @@ impl<T: DeserializeOwned> ClassAveragePricePattern<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Pattern struct for repeated tree structure.
|
||||
pub struct PeriodAveragePricePattern<T> {
|
||||
pub _10y: MetricPattern4<T>,
|
||||
pub _1m: MetricPattern4<T>,
|
||||
pub _1w: MetricPattern4<T>,
|
||||
pub _1y: MetricPattern4<T>,
|
||||
pub _2y: MetricPattern4<T>,
|
||||
pub _3m: MetricPattern4<T>,
|
||||
pub _3y: MetricPattern4<T>,
|
||||
pub _4y: MetricPattern4<T>,
|
||||
pub _5y: MetricPattern4<T>,
|
||||
pub _6m: MetricPattern4<T>,
|
||||
pub _6y: MetricPattern4<T>,
|
||||
pub _8y: MetricPattern4<T>,
|
||||
}
|
||||
|
||||
impl<T: DeserializeOwned> PeriodAveragePricePattern<T> {
|
||||
/// Create a new pattern node with accumulated metric name.
|
||||
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
|
||||
Self {
|
||||
_10y: MetricPattern4::new(client.clone(), _p("10y", &acc)),
|
||||
_1m: MetricPattern4::new(client.clone(), _p("1m", &acc)),
|
||||
_1w: MetricPattern4::new(client.clone(), _p("1w", &acc)),
|
||||
_1y: MetricPattern4::new(client.clone(), _p("1y", &acc)),
|
||||
_2y: MetricPattern4::new(client.clone(), _p("2y", &acc)),
|
||||
_3m: MetricPattern4::new(client.clone(), _p("3m", &acc)),
|
||||
_3y: MetricPattern4::new(client.clone(), _p("3y", &acc)),
|
||||
_4y: MetricPattern4::new(client.clone(), _p("4y", &acc)),
|
||||
_5y: MetricPattern4::new(client.clone(), _p("5y", &acc)),
|
||||
_6m: MetricPattern4::new(client.clone(), _p("6m", &acc)),
|
||||
_6y: MetricPattern4::new(client.clone(), _p("6y", &acc)),
|
||||
_8y: MetricPattern4::new(client.clone(), _p("8y", &acc)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Pattern struct for repeated tree structure.
|
||||
pub struct BitcoinPattern {
|
||||
pub average: MetricPattern2<Bitcoin>,
|
||||
@@ -1798,36 +1798,6 @@ impl AddrCountPattern {
|
||||
}
|
||||
}
|
||||
|
||||
/// Pattern struct for repeated tree structure.
|
||||
pub struct FullnessPattern<T> {
|
||||
pub average: MetricPattern2<T>,
|
||||
pub base: MetricPattern11<T>,
|
||||
pub max: MetricPattern2<T>,
|
||||
pub median: MetricPattern6<T>,
|
||||
pub min: MetricPattern2<T>,
|
||||
pub pct10: MetricPattern6<T>,
|
||||
pub pct25: MetricPattern6<T>,
|
||||
pub pct75: MetricPattern6<T>,
|
||||
pub pct90: MetricPattern6<T>,
|
||||
}
|
||||
|
||||
impl<T: DeserializeOwned> FullnessPattern<T> {
|
||||
/// Create a new pattern node with accumulated metric name.
|
||||
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
|
||||
Self {
|
||||
average: MetricPattern2::new(client.clone(), _m(&acc, "average")),
|
||||
base: MetricPattern11::new(client.clone(), acc.clone()),
|
||||
max: MetricPattern2::new(client.clone(), _m(&acc, "max")),
|
||||
median: MetricPattern6::new(client.clone(), _m(&acc, "median")),
|
||||
min: MetricPattern2::new(client.clone(), _m(&acc, "min")),
|
||||
pct10: MetricPattern6::new(client.clone(), _m(&acc, "pct10")),
|
||||
pct25: MetricPattern6::new(client.clone(), _m(&acc, "pct25")),
|
||||
pct75: MetricPattern6::new(client.clone(), _m(&acc, "pct75")),
|
||||
pct90: MetricPattern6::new(client.clone(), _m(&acc, "pct90")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Pattern struct for repeated tree structure.
|
||||
pub struct FeeRatePattern<T> {
|
||||
pub average: MetricPattern1<T>,
|
||||
@@ -1858,6 +1828,36 @@ impl<T: DeserializeOwned> FeeRatePattern<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Pattern struct for repeated tree structure.
|
||||
pub struct FullnessPattern<T> {
|
||||
pub average: MetricPattern2<T>,
|
||||
pub base: MetricPattern11<T>,
|
||||
pub max: MetricPattern2<T>,
|
||||
pub median: MetricPattern6<T>,
|
||||
pub min: MetricPattern2<T>,
|
||||
pub pct10: MetricPattern6<T>,
|
||||
pub pct25: MetricPattern6<T>,
|
||||
pub pct75: MetricPattern6<T>,
|
||||
pub pct90: MetricPattern6<T>,
|
||||
}
|
||||
|
||||
impl<T: DeserializeOwned> FullnessPattern<T> {
|
||||
/// Create a new pattern node with accumulated metric name.
|
||||
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
|
||||
Self {
|
||||
average: MetricPattern2::new(client.clone(), _m(&acc, "average")),
|
||||
base: MetricPattern11::new(client.clone(), acc.clone()),
|
||||
max: MetricPattern2::new(client.clone(), _m(&acc, "max")),
|
||||
median: MetricPattern6::new(client.clone(), _m(&acc, "median")),
|
||||
min: MetricPattern2::new(client.clone(), _m(&acc, "min")),
|
||||
pct10: MetricPattern6::new(client.clone(), _m(&acc, "pct10")),
|
||||
pct25: MetricPattern6::new(client.clone(), _m(&acc, "pct25")),
|
||||
pct75: MetricPattern6::new(client.clone(), _m(&acc, "pct75")),
|
||||
pct90: MetricPattern6::new(client.clone(), _m(&acc, "pct90")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Pattern struct for repeated tree structure.
|
||||
pub struct _0satsPattern {
|
||||
pub activity: ActivityPattern2,
|
||||
@@ -1914,6 +1914,32 @@ impl<T: DeserializeOwned> PhaseDailyCentsPattern<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Pattern struct for repeated tree structure.
|
||||
pub struct _0satsPattern2 {
|
||||
pub activity: ActivityPattern2,
|
||||
pub cost_basis: CostBasisPattern,
|
||||
pub outputs: OutputsPattern,
|
||||
pub realized: RealizedPattern,
|
||||
pub relative: RelativePattern4,
|
||||
pub supply: SupplyPattern2,
|
||||
pub unrealized: UnrealizedPattern,
|
||||
}
|
||||
|
||||
impl _0satsPattern2 {
|
||||
/// Create a new pattern node with accumulated metric name.
|
||||
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
|
||||
Self {
|
||||
activity: ActivityPattern2::new(client.clone(), acc.clone()),
|
||||
cost_basis: CostBasisPattern::new(client.clone(), acc.clone()),
|
||||
outputs: OutputsPattern::new(client.clone(), _m(&acc, "utxo_count")),
|
||||
realized: RealizedPattern::new(client.clone(), acc.clone()),
|
||||
relative: RelativePattern4::new(client.clone(), _m(&acc, "supply_in")),
|
||||
supply: SupplyPattern2::new(client.clone(), _m(&acc, "supply")),
|
||||
unrealized: UnrealizedPattern::new(client.clone(), acc.clone()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Pattern struct for repeated tree structure.
|
||||
pub struct _100btcPattern {
|
||||
pub activity: ActivityPattern2,
|
||||
@@ -1966,32 +1992,6 @@ impl PeriodCagrPattern {
|
||||
}
|
||||
}
|
||||
|
||||
/// Pattern struct for repeated tree structure.
|
||||
pub struct _0satsPattern2 {
|
||||
pub activity: ActivityPattern2,
|
||||
pub cost_basis: CostBasisPattern,
|
||||
pub outputs: OutputsPattern,
|
||||
pub realized: RealizedPattern,
|
||||
pub relative: RelativePattern4,
|
||||
pub supply: SupplyPattern2,
|
||||
pub unrealized: UnrealizedPattern,
|
||||
}
|
||||
|
||||
impl _0satsPattern2 {
|
||||
/// Create a new pattern node with accumulated metric name.
|
||||
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
|
||||
Self {
|
||||
activity: ActivityPattern2::new(client.clone(), acc.clone()),
|
||||
cost_basis: CostBasisPattern::new(client.clone(), acc.clone()),
|
||||
outputs: OutputsPattern::new(client.clone(), _m(&acc, "utxo_count")),
|
||||
realized: RealizedPattern::new(client.clone(), acc.clone()),
|
||||
relative: RelativePattern4::new(client.clone(), _m(&acc, "supply_in")),
|
||||
supply: SupplyPattern2::new(client.clone(), _m(&acc, "supply")),
|
||||
unrealized: UnrealizedPattern::new(client.clone(), acc.clone()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Pattern struct for repeated tree structure.
|
||||
pub struct _10yTo12yPattern {
|
||||
pub activity: ActivityPattern2,
|
||||
@@ -2018,6 +2018,32 @@ impl _10yTo12yPattern {
|
||||
}
|
||||
}
|
||||
|
||||
/// Pattern struct for repeated tree structure.
|
||||
pub struct _10yPattern {
|
||||
pub activity: ActivityPattern2,
|
||||
pub cost_basis: CostBasisPattern,
|
||||
pub outputs: OutputsPattern,
|
||||
pub realized: RealizedPattern4,
|
||||
pub relative: RelativePattern,
|
||||
pub supply: SupplyPattern2,
|
||||
pub unrealized: UnrealizedPattern,
|
||||
}
|
||||
|
||||
impl _10yPattern {
|
||||
/// Create a new pattern node with accumulated metric name.
|
||||
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
|
||||
Self {
|
||||
activity: ActivityPattern2::new(client.clone(), acc.clone()),
|
||||
cost_basis: CostBasisPattern::new(client.clone(), acc.clone()),
|
||||
outputs: OutputsPattern::new(client.clone(), _m(&acc, "utxo_count")),
|
||||
realized: RealizedPattern4::new(client.clone(), acc.clone()),
|
||||
relative: RelativePattern::new(client.clone(), acc.clone()),
|
||||
supply: SupplyPattern2::new(client.clone(), _m(&acc, "supply")),
|
||||
unrealized: UnrealizedPattern::new(client.clone(), acc.clone()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Pattern struct for repeated tree structure.
|
||||
pub struct UnrealizedPattern {
|
||||
pub neg_unrealized_loss: MetricPattern1<Dollars>,
|
||||
@@ -2044,32 +2070,6 @@ impl UnrealizedPattern {
|
||||
}
|
||||
}
|
||||
|
||||
/// Pattern struct for repeated tree structure.
|
||||
pub struct _10yPattern {
|
||||
pub activity: ActivityPattern2,
|
||||
pub cost_basis: CostBasisPattern,
|
||||
pub outputs: OutputsPattern,
|
||||
pub realized: RealizedPattern4,
|
||||
pub relative: RelativePattern,
|
||||
pub supply: SupplyPattern2,
|
||||
pub unrealized: UnrealizedPattern,
|
||||
}
|
||||
|
||||
impl _10yPattern {
|
||||
/// Create a new pattern node with accumulated metric name.
|
||||
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
|
||||
Self {
|
||||
activity: ActivityPattern2::new(client.clone(), acc.clone()),
|
||||
cost_basis: CostBasisPattern::new(client.clone(), acc.clone()),
|
||||
outputs: OutputsPattern::new(client.clone(), _m(&acc, "utxo_count")),
|
||||
realized: RealizedPattern4::new(client.clone(), acc.clone()),
|
||||
relative: RelativePattern::new(client.clone(), acc.clone()),
|
||||
supply: SupplyPattern2::new(client.clone(), _m(&acc, "supply")),
|
||||
unrealized: UnrealizedPattern::new(client.clone(), acc.clone()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Pattern struct for repeated tree structure.
|
||||
pub struct ActivityPattern2 {
|
||||
pub coinblocks_destroyed: BlockCountPattern<StoredF64>,
|
||||
@@ -2130,42 +2130,6 @@ impl CostBasisPattern2 {
|
||||
}
|
||||
}
|
||||
|
||||
/// Pattern struct for repeated tree structure.
|
||||
pub struct CoinbasePattern {
|
||||
pub bitcoin: BitcoinPattern,
|
||||
pub dollars: DollarsPattern<Dollars>,
|
||||
pub sats: DollarsPattern<Sats>,
|
||||
}
|
||||
|
||||
impl CoinbasePattern {
|
||||
/// Create a new pattern node with accumulated metric name.
|
||||
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
|
||||
Self {
|
||||
bitcoin: BitcoinPattern::new(client.clone(), _m(&acc, "btc")),
|
||||
dollars: DollarsPattern::new(client.clone(), _m(&acc, "usd")),
|
||||
sats: DollarsPattern::new(client.clone(), acc.clone()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Pattern struct for repeated tree structure.
|
||||
pub struct CoinbasePattern2 {
|
||||
pub bitcoin: BlockCountPattern<Bitcoin>,
|
||||
pub dollars: BlockCountPattern<Dollars>,
|
||||
pub sats: BlockCountPattern<Sats>,
|
||||
}
|
||||
|
||||
impl CoinbasePattern2 {
|
||||
/// Create a new pattern node with accumulated metric name.
|
||||
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
|
||||
Self {
|
||||
bitcoin: BlockCountPattern::new(client.clone(), _m(&acc, "btc")),
|
||||
dollars: BlockCountPattern::new(client.clone(), _m(&acc, "usd")),
|
||||
sats: BlockCountPattern::new(client.clone(), acc.clone()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Pattern struct for repeated tree structure.
|
||||
pub struct ActiveSupplyPattern {
|
||||
pub bitcoin: MetricPattern1<Bitcoin>,
|
||||
@@ -2202,6 +2166,24 @@ impl SegwitAdoptionPattern {
|
||||
}
|
||||
}
|
||||
|
||||
/// Pattern struct for repeated tree structure.
|
||||
pub struct CoinbasePattern2 {
|
||||
pub bitcoin: BlockCountPattern<Bitcoin>,
|
||||
pub dollars: BlockCountPattern<Dollars>,
|
||||
pub sats: BlockCountPattern<Sats>,
|
||||
}
|
||||
|
||||
impl CoinbasePattern2 {
|
||||
/// Create a new pattern node with accumulated metric name.
|
||||
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
|
||||
Self {
|
||||
bitcoin: BlockCountPattern::new(client.clone(), _m(&acc, "btc")),
|
||||
dollars: BlockCountPattern::new(client.clone(), _m(&acc, "usd")),
|
||||
sats: BlockCountPattern::new(client.clone(), acc.clone()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Pattern struct for repeated tree structure.
|
||||
pub struct UnclaimedRewardsPattern {
|
||||
pub bitcoin: BitcoinPattern2<Bitcoin>,
|
||||
@@ -2220,6 +2202,24 @@ impl UnclaimedRewardsPattern {
|
||||
}
|
||||
}
|
||||
|
||||
/// Pattern struct for repeated tree structure.
|
||||
pub struct CoinbasePattern {
|
||||
pub bitcoin: BitcoinPattern,
|
||||
pub dollars: DollarsPattern<Dollars>,
|
||||
pub sats: DollarsPattern<Sats>,
|
||||
}
|
||||
|
||||
impl CoinbasePattern {
|
||||
/// Create a new pattern node with accumulated metric name.
|
||||
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
|
||||
Self {
|
||||
bitcoin: BitcoinPattern::new(client.clone(), _m(&acc, "btc")),
|
||||
dollars: DollarsPattern::new(client.clone(), _m(&acc, "usd")),
|
||||
sats: DollarsPattern::new(client.clone(), acc.clone()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Pattern struct for repeated tree structure.
|
||||
pub struct _2015Pattern {
|
||||
pub bitcoin: MetricPattern4<Bitcoin>,
|
||||
@@ -2238,22 +2238,6 @@ impl _2015Pattern {
|
||||
}
|
||||
}
|
||||
|
||||
/// Pattern struct for repeated tree structure.
|
||||
pub struct SupplyPattern2 {
|
||||
pub halved: ActiveSupplyPattern,
|
||||
pub total: ActiveSupplyPattern,
|
||||
}
|
||||
|
||||
impl SupplyPattern2 {
|
||||
/// Create a new pattern node with accumulated metric name.
|
||||
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
|
||||
Self {
|
||||
halved: ActiveSupplyPattern::new(client.clone(), _m(&acc, "halved")),
|
||||
total: ActiveSupplyPattern::new(client.clone(), acc.clone()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Pattern struct for repeated tree structure.
|
||||
pub struct RelativePattern4 {
|
||||
pub supply_in_loss_rel_to_own_supply: MetricPattern1<StoredF64>,
|
||||
@@ -2270,6 +2254,22 @@ impl RelativePattern4 {
|
||||
}
|
||||
}
|
||||
|
||||
/// Pattern struct for repeated tree structure.
|
||||
pub struct SupplyPattern2 {
|
||||
pub halved: ActiveSupplyPattern,
|
||||
pub total: ActiveSupplyPattern,
|
||||
}
|
||||
|
||||
impl SupplyPattern2 {
|
||||
/// Create a new pattern node with accumulated metric name.
|
||||
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
|
||||
Self {
|
||||
halved: ActiveSupplyPattern::new(client.clone(), _m(&acc, "halved")),
|
||||
total: ActiveSupplyPattern::new(client.clone(), acc.clone()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Pattern struct for repeated tree structure.
|
||||
pub struct CostBasisPattern {
|
||||
pub max: MetricPattern1<Dollars>,
|
||||
@@ -4205,11 +4205,24 @@ impl MetricsTree_Market_Ath {
|
||||
/// Metrics tree node.
|
||||
pub struct MetricsTree_Market_Dca {
|
||||
pub class_average_price: ClassAveragePricePattern<Dollars>,
|
||||
pub class_days_in_loss: MetricsTree_Market_Dca_ClassDaysInLoss,
|
||||
pub class_days_in_profit: MetricsTree_Market_Dca_ClassDaysInProfit,
|
||||
pub class_max_drawdown: MetricsTree_Market_Dca_ClassMaxDrawdown,
|
||||
pub class_max_return: MetricsTree_Market_Dca_ClassMaxReturn,
|
||||
pub class_returns: MetricsTree_Market_Dca_ClassReturns,
|
||||
pub class_stack: MetricsTree_Market_Dca_ClassStack,
|
||||
pub period_average_price: PeriodAveragePricePattern<Dollars>,
|
||||
pub period_cagr: PeriodCagrPattern,
|
||||
pub period_days_in_loss: PeriodAveragePricePattern<StoredU32>,
|
||||
pub period_days_in_profit: PeriodAveragePricePattern<StoredU32>,
|
||||
pub period_lump_sum_days_in_loss: PeriodAveragePricePattern<StoredU32>,
|
||||
pub period_lump_sum_days_in_profit: PeriodAveragePricePattern<StoredU32>,
|
||||
pub period_lump_sum_max_drawdown: PeriodAveragePricePattern<StoredF32>,
|
||||
pub period_lump_sum_max_return: PeriodAveragePricePattern<StoredF32>,
|
||||
pub period_lump_sum_returns: PeriodAveragePricePattern<StoredF32>,
|
||||
pub period_lump_sum_stack: PeriodLumpSumStackPattern,
|
||||
pub period_max_drawdown: PeriodAveragePricePattern<StoredF32>,
|
||||
pub period_max_return: PeriodAveragePricePattern<StoredF32>,
|
||||
pub period_returns: PeriodAveragePricePattern<StoredF32>,
|
||||
pub period_stack: PeriodLumpSumStackPattern,
|
||||
}
|
||||
@@ -4218,17 +4231,170 @@ impl MetricsTree_Market_Dca {
|
||||
pub fn new(client: Arc<BrkClientBase>, base_path: String) -> Self {
|
||||
Self {
|
||||
class_average_price: ClassAveragePricePattern::new(client.clone(), "dca_class".to_string()),
|
||||
class_days_in_loss: MetricsTree_Market_Dca_ClassDaysInLoss::new(client.clone(), format!("{base_path}_class_days_in_loss")),
|
||||
class_days_in_profit: MetricsTree_Market_Dca_ClassDaysInProfit::new(client.clone(), format!("{base_path}_class_days_in_profit")),
|
||||
class_max_drawdown: MetricsTree_Market_Dca_ClassMaxDrawdown::new(client.clone(), format!("{base_path}_class_max_drawdown")),
|
||||
class_max_return: MetricsTree_Market_Dca_ClassMaxReturn::new(client.clone(), format!("{base_path}_class_max_return")),
|
||||
class_returns: MetricsTree_Market_Dca_ClassReturns::new(client.clone(), format!("{base_path}_class_returns")),
|
||||
class_stack: MetricsTree_Market_Dca_ClassStack::new(client.clone(), format!("{base_path}_class_stack")),
|
||||
period_average_price: PeriodAveragePricePattern::new(client.clone(), "dca_average_price".to_string()),
|
||||
period_cagr: PeriodCagrPattern::new(client.clone(), "dca_cagr".to_string()),
|
||||
period_days_in_loss: PeriodAveragePricePattern::new(client.clone(), "dca_days_in_loss".to_string()),
|
||||
period_days_in_profit: PeriodAveragePricePattern::new(client.clone(), "dca_days_in_profit".to_string()),
|
||||
period_lump_sum_days_in_loss: PeriodAveragePricePattern::new(client.clone(), "lump_sum_days_in_loss".to_string()),
|
||||
period_lump_sum_days_in_profit: PeriodAveragePricePattern::new(client.clone(), "lump_sum_days_in_profit".to_string()),
|
||||
period_lump_sum_max_drawdown: PeriodAveragePricePattern::new(client.clone(), "lump_sum_max_drawdown".to_string()),
|
||||
period_lump_sum_max_return: PeriodAveragePricePattern::new(client.clone(), "lump_sum_max_return".to_string()),
|
||||
period_lump_sum_returns: PeriodAveragePricePattern::new(client.clone(), "lump_sum_returns".to_string()),
|
||||
period_lump_sum_stack: PeriodLumpSumStackPattern::new(client.clone(), "lump_sum_stack".to_string()),
|
||||
period_max_drawdown: PeriodAveragePricePattern::new(client.clone(), "dca_max_drawdown".to_string()),
|
||||
period_max_return: PeriodAveragePricePattern::new(client.clone(), "dca_max_return".to_string()),
|
||||
period_returns: PeriodAveragePricePattern::new(client.clone(), "dca_returns".to_string()),
|
||||
period_stack: PeriodLumpSumStackPattern::new(client.clone(), "dca_stack".to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Metrics tree node.
|
||||
pub struct MetricsTree_Market_Dca_ClassDaysInLoss {
|
||||
pub _2015: MetricPattern4<StoredU32>,
|
||||
pub _2016: MetricPattern4<StoredU32>,
|
||||
pub _2017: MetricPattern4<StoredU32>,
|
||||
pub _2018: MetricPattern4<StoredU32>,
|
||||
pub _2019: MetricPattern4<StoredU32>,
|
||||
pub _2020: MetricPattern4<StoredU32>,
|
||||
pub _2021: MetricPattern4<StoredU32>,
|
||||
pub _2022: MetricPattern4<StoredU32>,
|
||||
pub _2023: MetricPattern4<StoredU32>,
|
||||
pub _2024: MetricPattern4<StoredU32>,
|
||||
pub _2025: MetricPattern4<StoredU32>,
|
||||
pub _2026: MetricPattern4<StoredU32>,
|
||||
}
|
||||
|
||||
impl MetricsTree_Market_Dca_ClassDaysInLoss {
|
||||
pub fn new(client: Arc<BrkClientBase>, base_path: String) -> Self {
|
||||
Self {
|
||||
_2015: MetricPattern4::new(client.clone(), "dca_class_2015_days_in_loss".to_string()),
|
||||
_2016: MetricPattern4::new(client.clone(), "dca_class_2016_days_in_loss".to_string()),
|
||||
_2017: MetricPattern4::new(client.clone(), "dca_class_2017_days_in_loss".to_string()),
|
||||
_2018: MetricPattern4::new(client.clone(), "dca_class_2018_days_in_loss".to_string()),
|
||||
_2019: MetricPattern4::new(client.clone(), "dca_class_2019_days_in_loss".to_string()),
|
||||
_2020: MetricPattern4::new(client.clone(), "dca_class_2020_days_in_loss".to_string()),
|
||||
_2021: MetricPattern4::new(client.clone(), "dca_class_2021_days_in_loss".to_string()),
|
||||
_2022: MetricPattern4::new(client.clone(), "dca_class_2022_days_in_loss".to_string()),
|
||||
_2023: MetricPattern4::new(client.clone(), "dca_class_2023_days_in_loss".to_string()),
|
||||
_2024: MetricPattern4::new(client.clone(), "dca_class_2024_days_in_loss".to_string()),
|
||||
_2025: MetricPattern4::new(client.clone(), "dca_class_2025_days_in_loss".to_string()),
|
||||
_2026: MetricPattern4::new(client.clone(), "dca_class_2026_days_in_loss".to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Metrics tree node.
|
||||
pub struct MetricsTree_Market_Dca_ClassDaysInProfit {
|
||||
pub _2015: MetricPattern4<StoredU32>,
|
||||
pub _2016: MetricPattern4<StoredU32>,
|
||||
pub _2017: MetricPattern4<StoredU32>,
|
||||
pub _2018: MetricPattern4<StoredU32>,
|
||||
pub _2019: MetricPattern4<StoredU32>,
|
||||
pub _2020: MetricPattern4<StoredU32>,
|
||||
pub _2021: MetricPattern4<StoredU32>,
|
||||
pub _2022: MetricPattern4<StoredU32>,
|
||||
pub _2023: MetricPattern4<StoredU32>,
|
||||
pub _2024: MetricPattern4<StoredU32>,
|
||||
pub _2025: MetricPattern4<StoredU32>,
|
||||
pub _2026: MetricPattern4<StoredU32>,
|
||||
}
|
||||
|
||||
impl MetricsTree_Market_Dca_ClassDaysInProfit {
|
||||
pub fn new(client: Arc<BrkClientBase>, base_path: String) -> Self {
|
||||
Self {
|
||||
_2015: MetricPattern4::new(client.clone(), "dca_class_2015_days_in_profit".to_string()),
|
||||
_2016: MetricPattern4::new(client.clone(), "dca_class_2016_days_in_profit".to_string()),
|
||||
_2017: MetricPattern4::new(client.clone(), "dca_class_2017_days_in_profit".to_string()),
|
||||
_2018: MetricPattern4::new(client.clone(), "dca_class_2018_days_in_profit".to_string()),
|
||||
_2019: MetricPattern4::new(client.clone(), "dca_class_2019_days_in_profit".to_string()),
|
||||
_2020: MetricPattern4::new(client.clone(), "dca_class_2020_days_in_profit".to_string()),
|
||||
_2021: MetricPattern4::new(client.clone(), "dca_class_2021_days_in_profit".to_string()),
|
||||
_2022: MetricPattern4::new(client.clone(), "dca_class_2022_days_in_profit".to_string()),
|
||||
_2023: MetricPattern4::new(client.clone(), "dca_class_2023_days_in_profit".to_string()),
|
||||
_2024: MetricPattern4::new(client.clone(), "dca_class_2024_days_in_profit".to_string()),
|
||||
_2025: MetricPattern4::new(client.clone(), "dca_class_2025_days_in_profit".to_string()),
|
||||
_2026: MetricPattern4::new(client.clone(), "dca_class_2026_days_in_profit".to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Metrics tree node.
|
||||
pub struct MetricsTree_Market_Dca_ClassMaxDrawdown {
|
||||
pub _2015: MetricPattern4<StoredF32>,
|
||||
pub _2016: MetricPattern4<StoredF32>,
|
||||
pub _2017: MetricPattern4<StoredF32>,
|
||||
pub _2018: MetricPattern4<StoredF32>,
|
||||
pub _2019: MetricPattern4<StoredF32>,
|
||||
pub _2020: MetricPattern4<StoredF32>,
|
||||
pub _2021: MetricPattern4<StoredF32>,
|
||||
pub _2022: MetricPattern4<StoredF32>,
|
||||
pub _2023: MetricPattern4<StoredF32>,
|
||||
pub _2024: MetricPattern4<StoredF32>,
|
||||
pub _2025: MetricPattern4<StoredF32>,
|
||||
pub _2026: MetricPattern4<StoredF32>,
|
||||
}
|
||||
|
||||
impl MetricsTree_Market_Dca_ClassMaxDrawdown {
|
||||
pub fn new(client: Arc<BrkClientBase>, base_path: String) -> Self {
|
||||
Self {
|
||||
_2015: MetricPattern4::new(client.clone(), "dca_class_2015_max_drawdown".to_string()),
|
||||
_2016: MetricPattern4::new(client.clone(), "dca_class_2016_max_drawdown".to_string()),
|
||||
_2017: MetricPattern4::new(client.clone(), "dca_class_2017_max_drawdown".to_string()),
|
||||
_2018: MetricPattern4::new(client.clone(), "dca_class_2018_max_drawdown".to_string()),
|
||||
_2019: MetricPattern4::new(client.clone(), "dca_class_2019_max_drawdown".to_string()),
|
||||
_2020: MetricPattern4::new(client.clone(), "dca_class_2020_max_drawdown".to_string()),
|
||||
_2021: MetricPattern4::new(client.clone(), "dca_class_2021_max_drawdown".to_string()),
|
||||
_2022: MetricPattern4::new(client.clone(), "dca_class_2022_max_drawdown".to_string()),
|
||||
_2023: MetricPattern4::new(client.clone(), "dca_class_2023_max_drawdown".to_string()),
|
||||
_2024: MetricPattern4::new(client.clone(), "dca_class_2024_max_drawdown".to_string()),
|
||||
_2025: MetricPattern4::new(client.clone(), "dca_class_2025_max_drawdown".to_string()),
|
||||
_2026: MetricPattern4::new(client.clone(), "dca_class_2026_max_drawdown".to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Metrics tree node.
|
||||
pub struct MetricsTree_Market_Dca_ClassMaxReturn {
|
||||
pub _2015: MetricPattern4<StoredF32>,
|
||||
pub _2016: MetricPattern4<StoredF32>,
|
||||
pub _2017: MetricPattern4<StoredF32>,
|
||||
pub _2018: MetricPattern4<StoredF32>,
|
||||
pub _2019: MetricPattern4<StoredF32>,
|
||||
pub _2020: MetricPattern4<StoredF32>,
|
||||
pub _2021: MetricPattern4<StoredF32>,
|
||||
pub _2022: MetricPattern4<StoredF32>,
|
||||
pub _2023: MetricPattern4<StoredF32>,
|
||||
pub _2024: MetricPattern4<StoredF32>,
|
||||
pub _2025: MetricPattern4<StoredF32>,
|
||||
pub _2026: MetricPattern4<StoredF32>,
|
||||
}
|
||||
|
||||
impl MetricsTree_Market_Dca_ClassMaxReturn {
|
||||
pub fn new(client: Arc<BrkClientBase>, base_path: String) -> Self {
|
||||
Self {
|
||||
_2015: MetricPattern4::new(client.clone(), "dca_class_2015_max_return".to_string()),
|
||||
_2016: MetricPattern4::new(client.clone(), "dca_class_2016_max_return".to_string()),
|
||||
_2017: MetricPattern4::new(client.clone(), "dca_class_2017_max_return".to_string()),
|
||||
_2018: MetricPattern4::new(client.clone(), "dca_class_2018_max_return".to_string()),
|
||||
_2019: MetricPattern4::new(client.clone(), "dca_class_2019_max_return".to_string()),
|
||||
_2020: MetricPattern4::new(client.clone(), "dca_class_2020_max_return".to_string()),
|
||||
_2021: MetricPattern4::new(client.clone(), "dca_class_2021_max_return".to_string()),
|
||||
_2022: MetricPattern4::new(client.clone(), "dca_class_2022_max_return".to_string()),
|
||||
_2023: MetricPattern4::new(client.clone(), "dca_class_2023_max_return".to_string()),
|
||||
_2024: MetricPattern4::new(client.clone(), "dca_class_2024_max_return".to_string()),
|
||||
_2025: MetricPattern4::new(client.clone(), "dca_class_2025_max_return".to_string()),
|
||||
_2026: MetricPattern4::new(client.clone(), "dca_class_2026_max_return".to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Metrics tree node.
|
||||
pub struct MetricsTree_Market_Dca_ClassReturns {
|
||||
pub _2015: MetricPattern4<StoredF32>,
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
use brk_error::Result;
|
||||
use brk_types::{Close, Dollars, StoredF32, StoredU32};
|
||||
use vecdb::Exit;
|
||||
|
||||
use super::Vecs;
|
||||
use super::{ByDcaClass, ByDcaPeriod, Vecs};
|
||||
use crate::{
|
||||
ComputeIndexes,
|
||||
internal::{ComputedFromDateLast, LazyBinaryFromDateLast},
|
||||
market::lookback,
|
||||
price,
|
||||
traits::{ComputeDCAAveragePriceViaLen, ComputeDCAStackViaLen, ComputeLumpSumStackViaLen},
|
||||
@@ -61,6 +63,17 @@ impl Vecs {
|
||||
})?;
|
||||
}
|
||||
|
||||
// DCA by period - profitability
|
||||
compute_period_profitability(
|
||||
&mut self.period_days_in_profit,
|
||||
&mut self.period_days_in_loss,
|
||||
&mut self.period_max_drawdown,
|
||||
&mut self.period_max_return,
|
||||
&self.period_returns,
|
||||
starting_indexes,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
// Lump sum by period - stack (for comparison with DCA)
|
||||
let lookback_dca = lookback.price_ago.as_dca_period();
|
||||
for (stack, lookback_price, days) in
|
||||
@@ -78,6 +91,17 @@ impl Vecs {
|
||||
})?;
|
||||
}
|
||||
|
||||
// Lump sum by period - profitability
|
||||
compute_period_profitability(
|
||||
&mut self.period_lump_sum_days_in_profit,
|
||||
&mut self.period_lump_sum_days_in_loss,
|
||||
&mut self.period_lump_sum_max_drawdown,
|
||||
&mut self.period_lump_sum_max_return,
|
||||
&self.period_lump_sum_returns,
|
||||
starting_indexes,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
// DCA by year class - stack and average_price
|
||||
let dateindexes = super::ByDcaClass::<()>::dateindexes();
|
||||
for ((stack, average_price), dateindex) in self
|
||||
@@ -102,6 +126,134 @@ impl Vecs {
|
||||
})?;
|
||||
}
|
||||
|
||||
// DCA by year class - profitability
|
||||
compute_class_profitability(
|
||||
&mut self.class_days_in_profit,
|
||||
&mut self.class_days_in_loss,
|
||||
&mut self.class_max_drawdown,
|
||||
&mut self.class_max_return,
|
||||
&self.class_returns,
|
||||
starting_indexes,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn compute_period_profitability(
|
||||
days_in_profit: &mut ByDcaPeriod<ComputedFromDateLast<StoredU32>>,
|
||||
days_in_loss: &mut ByDcaPeriod<ComputedFromDateLast<StoredU32>>,
|
||||
max_drawdown: &mut ByDcaPeriod<ComputedFromDateLast<StoredF32>>,
|
||||
max_return: &mut ByDcaPeriod<ComputedFromDateLast<StoredF32>>,
|
||||
returns: &ByDcaPeriod<LazyBinaryFromDateLast<StoredF32, Close<Dollars>, Dollars>>,
|
||||
starting_indexes: &ComputeIndexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
for ((((dip, dil), md), mr), (ret, days)) in days_in_profit
|
||||
.iter_mut()
|
||||
.zip(days_in_loss.iter_mut())
|
||||
.zip(max_drawdown.iter_mut())
|
||||
.zip(max_return.iter_mut())
|
||||
.zip(returns.iter_with_days())
|
||||
{
|
||||
dip.compute_all(starting_indexes, exit, |v| {
|
||||
Ok(v.compute_rolling_count(
|
||||
starting_indexes.dateindex,
|
||||
&ret.dateindex,
|
||||
days as usize,
|
||||
|r| f32::from(*r) > 0.0,
|
||||
exit,
|
||||
)?)
|
||||
})?;
|
||||
|
||||
dil.compute_all(starting_indexes, exit, |v| {
|
||||
Ok(v.compute_rolling_count(
|
||||
starting_indexes.dateindex,
|
||||
&ret.dateindex,
|
||||
days as usize,
|
||||
|r| f32::from(*r) < 0.0,
|
||||
exit,
|
||||
)?)
|
||||
})?;
|
||||
|
||||
md.compute_all(starting_indexes, exit, |v| {
|
||||
Ok(v.compute_min(
|
||||
starting_indexes.dateindex,
|
||||
&ret.dateindex,
|
||||
days as usize,
|
||||
exit,
|
||||
)?)
|
||||
})?;
|
||||
|
||||
mr.compute_all(starting_indexes, exit, |v| {
|
||||
Ok(v.compute_max(
|
||||
starting_indexes.dateindex,
|
||||
&ret.dateindex,
|
||||
days as usize,
|
||||
exit,
|
||||
)?)
|
||||
})?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn compute_class_profitability(
|
||||
days_in_profit: &mut ByDcaClass<ComputedFromDateLast<StoredU32>>,
|
||||
days_in_loss: &mut ByDcaClass<ComputedFromDateLast<StoredU32>>,
|
||||
max_drawdown: &mut ByDcaClass<ComputedFromDateLast<StoredF32>>,
|
||||
max_return: &mut ByDcaClass<ComputedFromDateLast<StoredF32>>,
|
||||
returns: &ByDcaClass<LazyBinaryFromDateLast<StoredF32, Close<Dollars>, Dollars>>,
|
||||
starting_indexes: &ComputeIndexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
let dateindexes = ByDcaClass::<()>::dateindexes();
|
||||
|
||||
for (((((dip, dil), md), mr), ret), from) in days_in_profit
|
||||
.iter_mut()
|
||||
.zip(days_in_loss.iter_mut())
|
||||
.zip(max_drawdown.iter_mut())
|
||||
.zip(max_return.iter_mut())
|
||||
.zip(returns.iter())
|
||||
.zip(dateindexes)
|
||||
{
|
||||
dip.compute_all(starting_indexes, exit, |v| {
|
||||
Ok(v.compute_cumulative_count_from(
|
||||
starting_indexes.dateindex,
|
||||
&ret.dateindex,
|
||||
from,
|
||||
|r| f32::from(*r) > 0.0,
|
||||
exit,
|
||||
)?)
|
||||
})?;
|
||||
|
||||
dil.compute_all(starting_indexes, exit, |v| {
|
||||
Ok(v.compute_cumulative_count_from(
|
||||
starting_indexes.dateindex,
|
||||
&ret.dateindex,
|
||||
from,
|
||||
|r| f32::from(*r) < 0.0,
|
||||
exit,
|
||||
)?)
|
||||
})?;
|
||||
|
||||
md.compute_all(starting_indexes, exit, |v| {
|
||||
Ok(v.compute_all_time_low_from(
|
||||
starting_indexes.dateindex,
|
||||
&ret.dateindex,
|
||||
from,
|
||||
exit,
|
||||
)?)
|
||||
})?;
|
||||
|
||||
mr.compute_all(starting_indexes, exit, |v| {
|
||||
Ok(v.compute_all_time_high_from(
|
||||
starting_indexes.dateindex,
|
||||
&ret.dateindex,
|
||||
from,
|
||||
exit,
|
||||
)?)
|
||||
})?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
use brk_error::Result;
|
||||
use brk_types::Version;
|
||||
use vecdb::Database;
|
||||
use vecdb::{Database, IterableCloneableVec};
|
||||
|
||||
use super::{ByDcaCagr, ByDcaClass, ByDcaPeriod, DCA_CLASS_NAMES, DCA_PERIOD_NAMES, Vecs};
|
||||
use crate::{
|
||||
indexes,
|
||||
internal::{ComputedFromDateLast, LazyBinaryFromDateLast, PercentageDiffCloseDollars, ValueFromDateLast},
|
||||
internal::{
|
||||
ComputedFromDateLast, LazyBinaryFromDateLast, PercentageDiffCloseDollars,
|
||||
ValueFromDateLast,
|
||||
},
|
||||
market::lookback,
|
||||
price,
|
||||
};
|
||||
|
||||
@@ -15,6 +19,7 @@ impl Vecs {
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
price: &price::Vecs,
|
||||
lookback: &lookback::Vecs,
|
||||
) -> Result<Self> {
|
||||
// DCA by period - stack (KISS)
|
||||
let period_stack = ByDcaPeriod::try_new(|name, _days| {
|
||||
@@ -48,6 +53,43 @@ impl Vecs {
|
||||
ComputedFromDateLast::forced_import(db, &format!("{name}_dca_cagr"), version, indexes)
|
||||
})?;
|
||||
|
||||
// DCA by period - profitability
|
||||
let period_days_in_profit = ByDcaPeriod::try_new(|name, _days| {
|
||||
ComputedFromDateLast::forced_import(
|
||||
db,
|
||||
&format!("{name}_dca_days_in_profit"),
|
||||
version + Version::ONE,
|
||||
indexes,
|
||||
)
|
||||
})?;
|
||||
|
||||
let period_days_in_loss = ByDcaPeriod::try_new(|name, _days| {
|
||||
ComputedFromDateLast::forced_import(
|
||||
db,
|
||||
&format!("{name}_dca_days_in_loss"),
|
||||
version + Version::ONE,
|
||||
indexes,
|
||||
)
|
||||
})?;
|
||||
|
||||
let period_max_drawdown = ByDcaPeriod::try_new(|name, _days| {
|
||||
ComputedFromDateLast::forced_import(
|
||||
db,
|
||||
&format!("{name}_dca_max_drawdown"),
|
||||
version,
|
||||
indexes,
|
||||
)
|
||||
})?;
|
||||
|
||||
let period_max_return = ByDcaPeriod::try_new(|name, _days| {
|
||||
ComputedFromDateLast::forced_import(
|
||||
db,
|
||||
&format!("{name}_dca_max_return"),
|
||||
version,
|
||||
indexes,
|
||||
)
|
||||
})?;
|
||||
|
||||
// Lump sum by period - stack (KISS)
|
||||
let period_lump_sum_stack = ByDcaPeriod::try_new(|name, _days| {
|
||||
ValueFromDateLast::forced_import(
|
||||
@@ -59,6 +101,58 @@ impl Vecs {
|
||||
)
|
||||
})?;
|
||||
|
||||
// Lump sum by period - returns
|
||||
let period_lump_sum_returns = DCA_PERIOD_NAMES
|
||||
.zip_ref(&lookback.price_ago.as_dca_period())
|
||||
.map(|(name, lookback_price)| {
|
||||
LazyBinaryFromDateLast::from_derived_last_and_computed_last::<
|
||||
PercentageDiffCloseDollars,
|
||||
>(
|
||||
&format!("{name}_lump_sum_returns"),
|
||||
version,
|
||||
price.usd.split.close.dateindex.boxed_clone(),
|
||||
&price.usd.split.close.rest,
|
||||
lookback_price,
|
||||
)
|
||||
});
|
||||
|
||||
// Lump sum by period - profitability
|
||||
let period_lump_sum_days_in_profit = ByDcaPeriod::try_new(|name, _days| {
|
||||
ComputedFromDateLast::forced_import(
|
||||
db,
|
||||
&format!("{name}_lump_sum_days_in_profit"),
|
||||
version + Version::ONE,
|
||||
indexes,
|
||||
)
|
||||
})?;
|
||||
|
||||
let period_lump_sum_days_in_loss = ByDcaPeriod::try_new(|name, _days| {
|
||||
ComputedFromDateLast::forced_import(
|
||||
db,
|
||||
&format!("{name}_lump_sum_days_in_loss"),
|
||||
version + Version::ONE,
|
||||
indexes,
|
||||
)
|
||||
})?;
|
||||
|
||||
let period_lump_sum_max_drawdown = ByDcaPeriod::try_new(|name, _days| {
|
||||
ComputedFromDateLast::forced_import(
|
||||
db,
|
||||
&format!("{name}_lump_sum_max_drawdown"),
|
||||
version,
|
||||
indexes,
|
||||
)
|
||||
})?;
|
||||
|
||||
let period_lump_sum_max_return = ByDcaPeriod::try_new(|name, _days| {
|
||||
ComputedFromDateLast::forced_import(
|
||||
db,
|
||||
&format!("{name}_lump_sum_max_return"),
|
||||
version,
|
||||
indexes,
|
||||
)
|
||||
})?;
|
||||
|
||||
// DCA by year class - stack (KISS)
|
||||
let class_stack = ByDcaClass::try_new(|name, _year, _dateindex| {
|
||||
ValueFromDateLast::forced_import(db, &format!("{name}_stack"), version, true, indexes)
|
||||
@@ -81,15 +175,65 @@ impl Vecs {
|
||||
)
|
||||
});
|
||||
|
||||
// DCA by year class - profitability
|
||||
let class_days_in_profit = ByDcaClass::try_new(|name, _year, _dateindex| {
|
||||
ComputedFromDateLast::forced_import(
|
||||
db,
|
||||
&format!("{name}_days_in_profit"),
|
||||
version,
|
||||
indexes,
|
||||
)
|
||||
})?;
|
||||
|
||||
let class_days_in_loss = ByDcaClass::try_new(|name, _year, _dateindex| {
|
||||
ComputedFromDateLast::forced_import(
|
||||
db,
|
||||
&format!("{name}_days_in_loss"),
|
||||
version,
|
||||
indexes,
|
||||
)
|
||||
})?;
|
||||
|
||||
let class_max_drawdown = ByDcaClass::try_new(|name, _year, _dateindex| {
|
||||
ComputedFromDateLast::forced_import(
|
||||
db,
|
||||
&format!("{name}_max_drawdown"),
|
||||
version,
|
||||
indexes,
|
||||
)
|
||||
})?;
|
||||
|
||||
let class_max_return = ByDcaClass::try_new(|name, _year, _dateindex| {
|
||||
ComputedFromDateLast::forced_import(
|
||||
db,
|
||||
&format!("{name}_max_return"),
|
||||
version,
|
||||
indexes,
|
||||
)
|
||||
})?;
|
||||
|
||||
Ok(Self {
|
||||
period_stack,
|
||||
period_average_price,
|
||||
period_returns,
|
||||
period_cagr,
|
||||
period_days_in_profit,
|
||||
period_days_in_loss,
|
||||
period_max_drawdown,
|
||||
period_max_return,
|
||||
period_lump_sum_stack,
|
||||
period_lump_sum_returns,
|
||||
period_lump_sum_days_in_profit,
|
||||
period_lump_sum_days_in_loss,
|
||||
period_lump_sum_max_drawdown,
|
||||
period_lump_sum_max_return,
|
||||
class_stack,
|
||||
class_average_price,
|
||||
class_returns,
|
||||
class_days_in_profit,
|
||||
class_days_in_loss,
|
||||
class_max_drawdown,
|
||||
class_max_return,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Close, Dollars, StoredF32};
|
||||
use brk_types::{Close, Dollars, StoredF32, StoredU32};
|
||||
|
||||
use super::{ByDcaCagr, ByDcaClass, ByDcaPeriod};
|
||||
use crate::internal::{ComputedFromDateLast, LazyBinaryFromDateLast, ValueFromDateLast};
|
||||
@@ -13,11 +13,30 @@ pub struct Vecs {
|
||||
pub period_returns: ByDcaPeriod<LazyBinaryFromDateLast<StoredF32, Close<Dollars>, Dollars>>,
|
||||
pub period_cagr: ByDcaCagr<ComputedFromDateLast<StoredF32>>,
|
||||
|
||||
// DCA by period - profitability
|
||||
pub period_days_in_profit: ByDcaPeriod<ComputedFromDateLast<StoredU32>>,
|
||||
pub period_days_in_loss: ByDcaPeriod<ComputedFromDateLast<StoredU32>>,
|
||||
pub period_max_drawdown: ByDcaPeriod<ComputedFromDateLast<StoredF32>>,
|
||||
pub period_max_return: ByDcaPeriod<ComputedFromDateLast<StoredF32>>,
|
||||
|
||||
// Lump sum by period (for comparison with DCA) - KISS types
|
||||
pub period_lump_sum_stack: ByDcaPeriod<ValueFromDateLast>,
|
||||
pub period_lump_sum_returns: ByDcaPeriod<LazyBinaryFromDateLast<StoredF32, Close<Dollars>, Dollars>>,
|
||||
|
||||
// Lump sum by period - profitability
|
||||
pub period_lump_sum_days_in_profit: ByDcaPeriod<ComputedFromDateLast<StoredU32>>,
|
||||
pub period_lump_sum_days_in_loss: ByDcaPeriod<ComputedFromDateLast<StoredU32>>,
|
||||
pub period_lump_sum_max_drawdown: ByDcaPeriod<ComputedFromDateLast<StoredF32>>,
|
||||
pub period_lump_sum_max_return: ByDcaPeriod<ComputedFromDateLast<StoredF32>>,
|
||||
|
||||
// DCA by year class - KISS types
|
||||
pub class_stack: ByDcaClass<ValueFromDateLast>,
|
||||
pub class_average_price: ByDcaClass<ComputedFromDateLast<Dollars>>,
|
||||
pub class_returns: ByDcaClass<LazyBinaryFromDateLast<StoredF32, Close<Dollars>, Dollars>>,
|
||||
|
||||
// DCA by year class - profitability
|
||||
pub class_days_in_profit: ByDcaClass<ComputedFromDateLast<StoredU32>>,
|
||||
pub class_days_in_loss: ByDcaClass<ComputedFromDateLast<StoredU32>>,
|
||||
pub class_max_drawdown: ByDcaClass<ComputedFromDateLast<StoredF32>>,
|
||||
pub class_max_return: ByDcaClass<ComputedFromDateLast<StoredF32>>,
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ impl Vecs {
|
||||
let volatility = VolatilityVecs::forced_import(version, &returns);
|
||||
let range = RangeVecs::forced_import(&db, version, indexes)?;
|
||||
let moving_average = MovingAverageVecs::forced_import(&db, version, indexes, Some(price))?;
|
||||
let dca = DcaVecs::forced_import(&db, version, indexes, price)?;
|
||||
let dca = DcaVecs::forced_import(&db, version, indexes, price, &lookback)?;
|
||||
let indicators = IndicatorsVecs::forced_import(
|
||||
&db,
|
||||
version,
|
||||
|
||||
@@ -49,6 +49,13 @@ impl From<u32> for StoredU32 {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<StoredU32> for u32 {
|
||||
#[inline]
|
||||
fn from(value: StoredU32) -> Self {
|
||||
value.0
|
||||
}
|
||||
}
|
||||
|
||||
impl From<StoredU32> for f32 {
|
||||
#[inline]
|
||||
fn from(value: StoredU32) -> Self {
|
||||
|
||||
+337
-195
@@ -1931,47 +1931,6 @@ function createPeriodLumpSumStackPattern(client, acc) {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @template T
|
||||
* @typedef {Object} PeriodAveragePricePattern
|
||||
* @property {MetricPattern4<T>} _10y
|
||||
* @property {MetricPattern4<T>} _1m
|
||||
* @property {MetricPattern4<T>} _1w
|
||||
* @property {MetricPattern4<T>} _1y
|
||||
* @property {MetricPattern4<T>} _2y
|
||||
* @property {MetricPattern4<T>} _3m
|
||||
* @property {MetricPattern4<T>} _3y
|
||||
* @property {MetricPattern4<T>} _4y
|
||||
* @property {MetricPattern4<T>} _5y
|
||||
* @property {MetricPattern4<T>} _6m
|
||||
* @property {MetricPattern4<T>} _6y
|
||||
* @property {MetricPattern4<T>} _8y
|
||||
*/
|
||||
|
||||
/**
|
||||
* Create a PeriodAveragePricePattern pattern node
|
||||
* @template T
|
||||
* @param {BrkClientBase} client
|
||||
* @param {string} acc - Accumulated metric name
|
||||
* @returns {PeriodAveragePricePattern<T>}
|
||||
*/
|
||||
function createPeriodAveragePricePattern(client, acc) {
|
||||
return {
|
||||
_10y: createMetricPattern4(client, _p('10y', acc)),
|
||||
_1m: createMetricPattern4(client, _p('1m', acc)),
|
||||
_1w: createMetricPattern4(client, _p('1w', acc)),
|
||||
_1y: createMetricPattern4(client, _p('1y', acc)),
|
||||
_2y: createMetricPattern4(client, _p('2y', acc)),
|
||||
_3m: createMetricPattern4(client, _p('3m', acc)),
|
||||
_3y: createMetricPattern4(client, _p('3y', acc)),
|
||||
_4y: createMetricPattern4(client, _p('4y', acc)),
|
||||
_5y: createMetricPattern4(client, _p('5y', acc)),
|
||||
_6m: createMetricPattern4(client, _p('6m', acc)),
|
||||
_6y: createMetricPattern4(client, _p('6y', acc)),
|
||||
_8y: createMetricPattern4(client, _p('8y', acc)),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @template T
|
||||
* @typedef {Object} ClassAveragePricePattern
|
||||
@@ -2013,6 +1972,47 @@ function createClassAveragePricePattern(client, acc) {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @template T
|
||||
* @typedef {Object} PeriodAveragePricePattern
|
||||
* @property {MetricPattern4<T>} _10y
|
||||
* @property {MetricPattern4<T>} _1m
|
||||
* @property {MetricPattern4<T>} _1w
|
||||
* @property {MetricPattern4<T>} _1y
|
||||
* @property {MetricPattern4<T>} _2y
|
||||
* @property {MetricPattern4<T>} _3m
|
||||
* @property {MetricPattern4<T>} _3y
|
||||
* @property {MetricPattern4<T>} _4y
|
||||
* @property {MetricPattern4<T>} _5y
|
||||
* @property {MetricPattern4<T>} _6m
|
||||
* @property {MetricPattern4<T>} _6y
|
||||
* @property {MetricPattern4<T>} _8y
|
||||
*/
|
||||
|
||||
/**
|
||||
* Create a PeriodAveragePricePattern pattern node
|
||||
* @template T
|
||||
* @param {BrkClientBase} client
|
||||
* @param {string} acc - Accumulated metric name
|
||||
* @returns {PeriodAveragePricePattern<T>}
|
||||
*/
|
||||
function createPeriodAveragePricePattern(client, acc) {
|
||||
return {
|
||||
_10y: createMetricPattern4(client, _p('10y', acc)),
|
||||
_1m: createMetricPattern4(client, _p('1m', acc)),
|
||||
_1w: createMetricPattern4(client, _p('1w', acc)),
|
||||
_1y: createMetricPattern4(client, _p('1y', acc)),
|
||||
_2y: createMetricPattern4(client, _p('2y', acc)),
|
||||
_3m: createMetricPattern4(client, _p('3m', acc)),
|
||||
_3y: createMetricPattern4(client, _p('3y', acc)),
|
||||
_4y: createMetricPattern4(client, _p('4y', acc)),
|
||||
_5y: createMetricPattern4(client, _p('5y', acc)),
|
||||
_6m: createMetricPattern4(client, _p('6m', acc)),
|
||||
_6y: createMetricPattern4(client, _p('6y', acc)),
|
||||
_8y: createMetricPattern4(client, _p('8y', acc)),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} BitcoinPattern
|
||||
* @property {MetricPattern2<Bitcoin>} average
|
||||
@@ -2229,41 +2229,6 @@ function createAddrCountPattern(client, acc) {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @template T
|
||||
* @typedef {Object} FullnessPattern
|
||||
* @property {MetricPattern2<T>} average
|
||||
* @property {MetricPattern11<T>} base
|
||||
* @property {MetricPattern2<T>} max
|
||||
* @property {MetricPattern6<T>} median
|
||||
* @property {MetricPattern2<T>} min
|
||||
* @property {MetricPattern6<T>} pct10
|
||||
* @property {MetricPattern6<T>} pct25
|
||||
* @property {MetricPattern6<T>} pct75
|
||||
* @property {MetricPattern6<T>} pct90
|
||||
*/
|
||||
|
||||
/**
|
||||
* Create a FullnessPattern pattern node
|
||||
* @template T
|
||||
* @param {BrkClientBase} client
|
||||
* @param {string} acc - Accumulated metric name
|
||||
* @returns {FullnessPattern<T>}
|
||||
*/
|
||||
function createFullnessPattern(client, acc) {
|
||||
return {
|
||||
average: createMetricPattern2(client, _m(acc, 'average')),
|
||||
base: createMetricPattern11(client, acc),
|
||||
max: createMetricPattern2(client, _m(acc, 'max')),
|
||||
median: createMetricPattern6(client, _m(acc, 'median')),
|
||||
min: createMetricPattern2(client, _m(acc, 'min')),
|
||||
pct10: createMetricPattern6(client, _m(acc, 'pct10')),
|
||||
pct25: createMetricPattern6(client, _m(acc, 'pct25')),
|
||||
pct75: createMetricPattern6(client, _m(acc, 'pct75')),
|
||||
pct90: createMetricPattern6(client, _m(acc, 'pct90')),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @template T
|
||||
* @typedef {Object} FeeRatePattern
|
||||
@@ -2299,6 +2264,41 @@ function createFeeRatePattern(client, acc) {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @template T
|
||||
* @typedef {Object} FullnessPattern
|
||||
* @property {MetricPattern2<T>} average
|
||||
* @property {MetricPattern11<T>} base
|
||||
* @property {MetricPattern2<T>} max
|
||||
* @property {MetricPattern6<T>} median
|
||||
* @property {MetricPattern2<T>} min
|
||||
* @property {MetricPattern6<T>} pct10
|
||||
* @property {MetricPattern6<T>} pct25
|
||||
* @property {MetricPattern6<T>} pct75
|
||||
* @property {MetricPattern6<T>} pct90
|
||||
*/
|
||||
|
||||
/**
|
||||
* Create a FullnessPattern pattern node
|
||||
* @template T
|
||||
* @param {BrkClientBase} client
|
||||
* @param {string} acc - Accumulated metric name
|
||||
* @returns {FullnessPattern<T>}
|
||||
*/
|
||||
function createFullnessPattern(client, acc) {
|
||||
return {
|
||||
average: createMetricPattern2(client, _m(acc, 'average')),
|
||||
base: createMetricPattern11(client, acc),
|
||||
max: createMetricPattern2(client, _m(acc, 'max')),
|
||||
median: createMetricPattern6(client, _m(acc, 'median')),
|
||||
min: createMetricPattern2(client, _m(acc, 'min')),
|
||||
pct10: createMetricPattern6(client, _m(acc, 'pct10')),
|
||||
pct25: createMetricPattern6(client, _m(acc, 'pct25')),
|
||||
pct75: createMetricPattern6(client, _m(acc, 'pct75')),
|
||||
pct90: createMetricPattern6(client, _m(acc, 'pct90')),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} _0satsPattern
|
||||
* @property {ActivityPattern2} activity
|
||||
@@ -2363,6 +2363,35 @@ function createPhaseDailyCentsPattern(client, acc) {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} _0satsPattern2
|
||||
* @property {ActivityPattern2} activity
|
||||
* @property {CostBasisPattern} costBasis
|
||||
* @property {OutputsPattern} outputs
|
||||
* @property {RealizedPattern} realized
|
||||
* @property {RelativePattern4} relative
|
||||
* @property {SupplyPattern2} supply
|
||||
* @property {UnrealizedPattern} unrealized
|
||||
*/
|
||||
|
||||
/**
|
||||
* Create a _0satsPattern2 pattern node
|
||||
* @param {BrkClientBase} client
|
||||
* @param {string} acc - Accumulated metric name
|
||||
* @returns {_0satsPattern2}
|
||||
*/
|
||||
function create_0satsPattern2(client, acc) {
|
||||
return {
|
||||
activity: createActivityPattern2(client, acc),
|
||||
costBasis: createCostBasisPattern(client, acc),
|
||||
outputs: createOutputsPattern(client, _m(acc, 'utxo_count')),
|
||||
realized: createRealizedPattern(client, acc),
|
||||
relative: createRelativePattern4(client, _m(acc, 'supply_in')),
|
||||
supply: createSupplyPattern2(client, _m(acc, 'supply')),
|
||||
unrealized: createUnrealizedPattern(client, acc),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} _100btcPattern
|
||||
* @property {ActivityPattern2} activity
|
||||
@@ -2421,35 +2450,6 @@ function createPeriodCagrPattern(client, acc) {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} _0satsPattern2
|
||||
* @property {ActivityPattern2} activity
|
||||
* @property {CostBasisPattern} costBasis
|
||||
* @property {OutputsPattern} outputs
|
||||
* @property {RealizedPattern} realized
|
||||
* @property {RelativePattern4} relative
|
||||
* @property {SupplyPattern2} supply
|
||||
* @property {UnrealizedPattern} unrealized
|
||||
*/
|
||||
|
||||
/**
|
||||
* Create a _0satsPattern2 pattern node
|
||||
* @param {BrkClientBase} client
|
||||
* @param {string} acc - Accumulated metric name
|
||||
* @returns {_0satsPattern2}
|
||||
*/
|
||||
function create_0satsPattern2(client, acc) {
|
||||
return {
|
||||
activity: createActivityPattern2(client, acc),
|
||||
costBasis: createCostBasisPattern(client, acc),
|
||||
outputs: createOutputsPattern(client, _m(acc, 'utxo_count')),
|
||||
realized: createRealizedPattern(client, acc),
|
||||
relative: createRelativePattern4(client, _m(acc, 'supply_in')),
|
||||
supply: createSupplyPattern2(client, _m(acc, 'supply')),
|
||||
unrealized: createUnrealizedPattern(client, acc),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} _10yTo12yPattern
|
||||
* @property {ActivityPattern2} activity
|
||||
@@ -2479,6 +2479,35 @@ function create_10yTo12yPattern(client, acc) {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} _10yPattern
|
||||
* @property {ActivityPattern2} activity
|
||||
* @property {CostBasisPattern} costBasis
|
||||
* @property {OutputsPattern} outputs
|
||||
* @property {RealizedPattern4} realized
|
||||
* @property {RelativePattern} relative
|
||||
* @property {SupplyPattern2} supply
|
||||
* @property {UnrealizedPattern} unrealized
|
||||
*/
|
||||
|
||||
/**
|
||||
* Create a _10yPattern pattern node
|
||||
* @param {BrkClientBase} client
|
||||
* @param {string} acc - Accumulated metric name
|
||||
* @returns {_10yPattern}
|
||||
*/
|
||||
function create_10yPattern(client, acc) {
|
||||
return {
|
||||
activity: createActivityPattern2(client, acc),
|
||||
costBasis: createCostBasisPattern(client, acc),
|
||||
outputs: createOutputsPattern(client, _m(acc, 'utxo_count')),
|
||||
realized: createRealizedPattern4(client, acc),
|
||||
relative: createRelativePattern(client, acc),
|
||||
supply: createSupplyPattern2(client, _m(acc, 'supply')),
|
||||
unrealized: createUnrealizedPattern(client, acc),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} UnrealizedPattern
|
||||
* @property {MetricPattern1<Dollars>} negUnrealizedLoss
|
||||
@@ -2508,35 +2537,6 @@ function createUnrealizedPattern(client, acc) {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} _10yPattern
|
||||
* @property {ActivityPattern2} activity
|
||||
* @property {CostBasisPattern} costBasis
|
||||
* @property {OutputsPattern} outputs
|
||||
* @property {RealizedPattern4} realized
|
||||
* @property {RelativePattern} relative
|
||||
* @property {SupplyPattern2} supply
|
||||
* @property {UnrealizedPattern} unrealized
|
||||
*/
|
||||
|
||||
/**
|
||||
* Create a _10yPattern pattern node
|
||||
* @param {BrkClientBase} client
|
||||
* @param {string} acc - Accumulated metric name
|
||||
* @returns {_10yPattern}
|
||||
*/
|
||||
function create_10yPattern(client, acc) {
|
||||
return {
|
||||
activity: createActivityPattern2(client, acc),
|
||||
costBasis: createCostBasisPattern(client, acc),
|
||||
outputs: createOutputsPattern(client, _m(acc, 'utxo_count')),
|
||||
realized: createRealizedPattern4(client, acc),
|
||||
relative: createRelativePattern(client, acc),
|
||||
supply: createSupplyPattern2(client, _m(acc, 'supply')),
|
||||
unrealized: createUnrealizedPattern(client, acc),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} ActivityPattern2
|
||||
* @property {BlockCountPattern<StoredF64>} coinblocksDestroyed
|
||||
@@ -2608,48 +2608,6 @@ function createCostBasisPattern2(client, acc) {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} CoinbasePattern
|
||||
* @property {BitcoinPattern} bitcoin
|
||||
* @property {DollarsPattern<Dollars>} dollars
|
||||
* @property {DollarsPattern<Sats>} sats
|
||||
*/
|
||||
|
||||
/**
|
||||
* Create a CoinbasePattern pattern node
|
||||
* @param {BrkClientBase} client
|
||||
* @param {string} acc - Accumulated metric name
|
||||
* @returns {CoinbasePattern}
|
||||
*/
|
||||
function createCoinbasePattern(client, acc) {
|
||||
return {
|
||||
bitcoin: createBitcoinPattern(client, _m(acc, 'btc')),
|
||||
dollars: createDollarsPattern(client, _m(acc, 'usd')),
|
||||
sats: createDollarsPattern(client, acc),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} CoinbasePattern2
|
||||
* @property {BlockCountPattern<Bitcoin>} bitcoin
|
||||
* @property {BlockCountPattern<Dollars>} dollars
|
||||
* @property {BlockCountPattern<Sats>} sats
|
||||
*/
|
||||
|
||||
/**
|
||||
* Create a CoinbasePattern2 pattern node
|
||||
* @param {BrkClientBase} client
|
||||
* @param {string} acc - Accumulated metric name
|
||||
* @returns {CoinbasePattern2}
|
||||
*/
|
||||
function createCoinbasePattern2(client, acc) {
|
||||
return {
|
||||
bitcoin: createBlockCountPattern(client, _m(acc, 'btc')),
|
||||
dollars: createBlockCountPattern(client, _m(acc, 'usd')),
|
||||
sats: createBlockCountPattern(client, acc),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} ActiveSupplyPattern
|
||||
* @property {MetricPattern1<Bitcoin>} bitcoin
|
||||
@@ -2692,6 +2650,27 @@ function createSegwitAdoptionPattern(client, acc) {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} CoinbasePattern2
|
||||
* @property {BlockCountPattern<Bitcoin>} bitcoin
|
||||
* @property {BlockCountPattern<Dollars>} dollars
|
||||
* @property {BlockCountPattern<Sats>} sats
|
||||
*/
|
||||
|
||||
/**
|
||||
* Create a CoinbasePattern2 pattern node
|
||||
* @param {BrkClientBase} client
|
||||
* @param {string} acc - Accumulated metric name
|
||||
* @returns {CoinbasePattern2}
|
||||
*/
|
||||
function createCoinbasePattern2(client, acc) {
|
||||
return {
|
||||
bitcoin: createBlockCountPattern(client, _m(acc, 'btc')),
|
||||
dollars: createBlockCountPattern(client, _m(acc, 'usd')),
|
||||
sats: createBlockCountPattern(client, acc),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} UnclaimedRewardsPattern
|
||||
* @property {BitcoinPattern2<Bitcoin>} bitcoin
|
||||
@@ -2713,6 +2692,27 @@ function createUnclaimedRewardsPattern(client, acc) {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} CoinbasePattern
|
||||
* @property {BitcoinPattern} bitcoin
|
||||
* @property {DollarsPattern<Dollars>} dollars
|
||||
* @property {DollarsPattern<Sats>} sats
|
||||
*/
|
||||
|
||||
/**
|
||||
* Create a CoinbasePattern pattern node
|
||||
* @param {BrkClientBase} client
|
||||
* @param {string} acc - Accumulated metric name
|
||||
* @returns {CoinbasePattern}
|
||||
*/
|
||||
function createCoinbasePattern(client, acc) {
|
||||
return {
|
||||
bitcoin: createBitcoinPattern(client, _m(acc, 'btc')),
|
||||
dollars: createDollarsPattern(client, _m(acc, 'usd')),
|
||||
sats: createDollarsPattern(client, acc),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} _2015Pattern
|
||||
* @property {MetricPattern4<Bitcoin>} bitcoin
|
||||
@@ -2734,25 +2734,6 @@ function create_2015Pattern(client, acc) {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} SupplyPattern2
|
||||
* @property {ActiveSupplyPattern} halved
|
||||
* @property {ActiveSupplyPattern} total
|
||||
*/
|
||||
|
||||
/**
|
||||
* Create a SupplyPattern2 pattern node
|
||||
* @param {BrkClientBase} client
|
||||
* @param {string} acc - Accumulated metric name
|
||||
* @returns {SupplyPattern2}
|
||||
*/
|
||||
function createSupplyPattern2(client, acc) {
|
||||
return {
|
||||
halved: createActiveSupplyPattern(client, _m(acc, 'halved')),
|
||||
total: createActiveSupplyPattern(client, acc),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} RelativePattern4
|
||||
* @property {MetricPattern1<StoredF64>} supplyInLossRelToOwnSupply
|
||||
@@ -2772,6 +2753,25 @@ function createRelativePattern4(client, acc) {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} SupplyPattern2
|
||||
* @property {ActiveSupplyPattern} halved
|
||||
* @property {ActiveSupplyPattern} total
|
||||
*/
|
||||
|
||||
/**
|
||||
* Create a SupplyPattern2 pattern node
|
||||
* @param {BrkClientBase} client
|
||||
* @param {string} acc - Accumulated metric name
|
||||
* @returns {SupplyPattern2}
|
||||
*/
|
||||
function createSupplyPattern2(client, acc) {
|
||||
return {
|
||||
halved: createActiveSupplyPattern(client, _m(acc, 'halved')),
|
||||
total: createActiveSupplyPattern(client, acc),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} CostBasisPattern
|
||||
* @property {MetricPattern1<Dollars>} max
|
||||
@@ -3712,15 +3712,92 @@ function createOutputsPattern(client, acc) {
|
||||
/**
|
||||
* @typedef {Object} MetricsTree_Market_Dca
|
||||
* @property {ClassAveragePricePattern<Dollars>} classAveragePrice
|
||||
* @property {MetricsTree_Market_Dca_ClassDaysInLoss} classDaysInLoss
|
||||
* @property {MetricsTree_Market_Dca_ClassDaysInProfit} classDaysInProfit
|
||||
* @property {MetricsTree_Market_Dca_ClassMaxDrawdown} classMaxDrawdown
|
||||
* @property {MetricsTree_Market_Dca_ClassMaxReturn} classMaxReturn
|
||||
* @property {MetricsTree_Market_Dca_ClassReturns} classReturns
|
||||
* @property {MetricsTree_Market_Dca_ClassStack} classStack
|
||||
* @property {PeriodAveragePricePattern<Dollars>} periodAveragePrice
|
||||
* @property {PeriodCagrPattern} periodCagr
|
||||
* @property {PeriodAveragePricePattern<StoredU32>} periodDaysInLoss
|
||||
* @property {PeriodAveragePricePattern<StoredU32>} periodDaysInProfit
|
||||
* @property {PeriodAveragePricePattern<StoredU32>} periodLumpSumDaysInLoss
|
||||
* @property {PeriodAveragePricePattern<StoredU32>} periodLumpSumDaysInProfit
|
||||
* @property {PeriodAveragePricePattern<StoredF32>} periodLumpSumMaxDrawdown
|
||||
* @property {PeriodAveragePricePattern<StoredF32>} periodLumpSumMaxReturn
|
||||
* @property {PeriodAveragePricePattern<StoredF32>} periodLumpSumReturns
|
||||
* @property {PeriodLumpSumStackPattern} periodLumpSumStack
|
||||
* @property {PeriodAveragePricePattern<StoredF32>} periodMaxDrawdown
|
||||
* @property {PeriodAveragePricePattern<StoredF32>} periodMaxReturn
|
||||
* @property {PeriodAveragePricePattern<StoredF32>} periodReturns
|
||||
* @property {PeriodLumpSumStackPattern} periodStack
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} MetricsTree_Market_Dca_ClassDaysInLoss
|
||||
* @property {MetricPattern4<StoredU32>} _2015
|
||||
* @property {MetricPattern4<StoredU32>} _2016
|
||||
* @property {MetricPattern4<StoredU32>} _2017
|
||||
* @property {MetricPattern4<StoredU32>} _2018
|
||||
* @property {MetricPattern4<StoredU32>} _2019
|
||||
* @property {MetricPattern4<StoredU32>} _2020
|
||||
* @property {MetricPattern4<StoredU32>} _2021
|
||||
* @property {MetricPattern4<StoredU32>} _2022
|
||||
* @property {MetricPattern4<StoredU32>} _2023
|
||||
* @property {MetricPattern4<StoredU32>} _2024
|
||||
* @property {MetricPattern4<StoredU32>} _2025
|
||||
* @property {MetricPattern4<StoredU32>} _2026
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} MetricsTree_Market_Dca_ClassDaysInProfit
|
||||
* @property {MetricPattern4<StoredU32>} _2015
|
||||
* @property {MetricPattern4<StoredU32>} _2016
|
||||
* @property {MetricPattern4<StoredU32>} _2017
|
||||
* @property {MetricPattern4<StoredU32>} _2018
|
||||
* @property {MetricPattern4<StoredU32>} _2019
|
||||
* @property {MetricPattern4<StoredU32>} _2020
|
||||
* @property {MetricPattern4<StoredU32>} _2021
|
||||
* @property {MetricPattern4<StoredU32>} _2022
|
||||
* @property {MetricPattern4<StoredU32>} _2023
|
||||
* @property {MetricPattern4<StoredU32>} _2024
|
||||
* @property {MetricPattern4<StoredU32>} _2025
|
||||
* @property {MetricPattern4<StoredU32>} _2026
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} MetricsTree_Market_Dca_ClassMaxDrawdown
|
||||
* @property {MetricPattern4<StoredF32>} _2015
|
||||
* @property {MetricPattern4<StoredF32>} _2016
|
||||
* @property {MetricPattern4<StoredF32>} _2017
|
||||
* @property {MetricPattern4<StoredF32>} _2018
|
||||
* @property {MetricPattern4<StoredF32>} _2019
|
||||
* @property {MetricPattern4<StoredF32>} _2020
|
||||
* @property {MetricPattern4<StoredF32>} _2021
|
||||
* @property {MetricPattern4<StoredF32>} _2022
|
||||
* @property {MetricPattern4<StoredF32>} _2023
|
||||
* @property {MetricPattern4<StoredF32>} _2024
|
||||
* @property {MetricPattern4<StoredF32>} _2025
|
||||
* @property {MetricPattern4<StoredF32>} _2026
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} MetricsTree_Market_Dca_ClassMaxReturn
|
||||
* @property {MetricPattern4<StoredF32>} _2015
|
||||
* @property {MetricPattern4<StoredF32>} _2016
|
||||
* @property {MetricPattern4<StoredF32>} _2017
|
||||
* @property {MetricPattern4<StoredF32>} _2018
|
||||
* @property {MetricPattern4<StoredF32>} _2019
|
||||
* @property {MetricPattern4<StoredF32>} _2020
|
||||
* @property {MetricPattern4<StoredF32>} _2021
|
||||
* @property {MetricPattern4<StoredF32>} _2022
|
||||
* @property {MetricPattern4<StoredF32>} _2023
|
||||
* @property {MetricPattern4<StoredF32>} _2024
|
||||
* @property {MetricPattern4<StoredF32>} _2025
|
||||
* @property {MetricPattern4<StoredF32>} _2026
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} MetricsTree_Market_Dca_ClassReturns
|
||||
* @property {MetricPattern4<StoredF32>} _2015
|
||||
@@ -5740,6 +5817,62 @@ class BrkClient extends BrkClientBase {
|
||||
},
|
||||
dca: {
|
||||
classAveragePrice: createClassAveragePricePattern(this, 'dca_class'),
|
||||
classDaysInLoss: {
|
||||
_2015: createMetricPattern4(this, 'dca_class_2015_days_in_loss'),
|
||||
_2016: createMetricPattern4(this, 'dca_class_2016_days_in_loss'),
|
||||
_2017: createMetricPattern4(this, 'dca_class_2017_days_in_loss'),
|
||||
_2018: createMetricPattern4(this, 'dca_class_2018_days_in_loss'),
|
||||
_2019: createMetricPattern4(this, 'dca_class_2019_days_in_loss'),
|
||||
_2020: createMetricPattern4(this, 'dca_class_2020_days_in_loss'),
|
||||
_2021: createMetricPattern4(this, 'dca_class_2021_days_in_loss'),
|
||||
_2022: createMetricPattern4(this, 'dca_class_2022_days_in_loss'),
|
||||
_2023: createMetricPattern4(this, 'dca_class_2023_days_in_loss'),
|
||||
_2024: createMetricPattern4(this, 'dca_class_2024_days_in_loss'),
|
||||
_2025: createMetricPattern4(this, 'dca_class_2025_days_in_loss'),
|
||||
_2026: createMetricPattern4(this, 'dca_class_2026_days_in_loss'),
|
||||
},
|
||||
classDaysInProfit: {
|
||||
_2015: createMetricPattern4(this, 'dca_class_2015_days_in_profit'),
|
||||
_2016: createMetricPattern4(this, 'dca_class_2016_days_in_profit'),
|
||||
_2017: createMetricPattern4(this, 'dca_class_2017_days_in_profit'),
|
||||
_2018: createMetricPattern4(this, 'dca_class_2018_days_in_profit'),
|
||||
_2019: createMetricPattern4(this, 'dca_class_2019_days_in_profit'),
|
||||
_2020: createMetricPattern4(this, 'dca_class_2020_days_in_profit'),
|
||||
_2021: createMetricPattern4(this, 'dca_class_2021_days_in_profit'),
|
||||
_2022: createMetricPattern4(this, 'dca_class_2022_days_in_profit'),
|
||||
_2023: createMetricPattern4(this, 'dca_class_2023_days_in_profit'),
|
||||
_2024: createMetricPattern4(this, 'dca_class_2024_days_in_profit'),
|
||||
_2025: createMetricPattern4(this, 'dca_class_2025_days_in_profit'),
|
||||
_2026: createMetricPattern4(this, 'dca_class_2026_days_in_profit'),
|
||||
},
|
||||
classMaxDrawdown: {
|
||||
_2015: createMetricPattern4(this, 'dca_class_2015_max_drawdown'),
|
||||
_2016: createMetricPattern4(this, 'dca_class_2016_max_drawdown'),
|
||||
_2017: createMetricPattern4(this, 'dca_class_2017_max_drawdown'),
|
||||
_2018: createMetricPattern4(this, 'dca_class_2018_max_drawdown'),
|
||||
_2019: createMetricPattern4(this, 'dca_class_2019_max_drawdown'),
|
||||
_2020: createMetricPattern4(this, 'dca_class_2020_max_drawdown'),
|
||||
_2021: createMetricPattern4(this, 'dca_class_2021_max_drawdown'),
|
||||
_2022: createMetricPattern4(this, 'dca_class_2022_max_drawdown'),
|
||||
_2023: createMetricPattern4(this, 'dca_class_2023_max_drawdown'),
|
||||
_2024: createMetricPattern4(this, 'dca_class_2024_max_drawdown'),
|
||||
_2025: createMetricPattern4(this, 'dca_class_2025_max_drawdown'),
|
||||
_2026: createMetricPattern4(this, 'dca_class_2026_max_drawdown'),
|
||||
},
|
||||
classMaxReturn: {
|
||||
_2015: createMetricPattern4(this, 'dca_class_2015_max_return'),
|
||||
_2016: createMetricPattern4(this, 'dca_class_2016_max_return'),
|
||||
_2017: createMetricPattern4(this, 'dca_class_2017_max_return'),
|
||||
_2018: createMetricPattern4(this, 'dca_class_2018_max_return'),
|
||||
_2019: createMetricPattern4(this, 'dca_class_2019_max_return'),
|
||||
_2020: createMetricPattern4(this, 'dca_class_2020_max_return'),
|
||||
_2021: createMetricPattern4(this, 'dca_class_2021_max_return'),
|
||||
_2022: createMetricPattern4(this, 'dca_class_2022_max_return'),
|
||||
_2023: createMetricPattern4(this, 'dca_class_2023_max_return'),
|
||||
_2024: createMetricPattern4(this, 'dca_class_2024_max_return'),
|
||||
_2025: createMetricPattern4(this, 'dca_class_2025_max_return'),
|
||||
_2026: createMetricPattern4(this, 'dca_class_2026_max_return'),
|
||||
},
|
||||
classReturns: {
|
||||
_2015: createMetricPattern4(this, 'dca_class_2015_returns'),
|
||||
_2016: createMetricPattern4(this, 'dca_class_2016_returns'),
|
||||
@@ -5770,7 +5903,16 @@ class BrkClient extends BrkClientBase {
|
||||
},
|
||||
periodAveragePrice: createPeriodAveragePricePattern(this, 'dca_average_price'),
|
||||
periodCagr: createPeriodCagrPattern(this, 'dca_cagr'),
|
||||
periodDaysInLoss: createPeriodAveragePricePattern(this, 'dca_days_in_loss'),
|
||||
periodDaysInProfit: createPeriodAveragePricePattern(this, 'dca_days_in_profit'),
|
||||
periodLumpSumDaysInLoss: createPeriodAveragePricePattern(this, 'lump_sum_days_in_loss'),
|
||||
periodLumpSumDaysInProfit: createPeriodAveragePricePattern(this, 'lump_sum_days_in_profit'),
|
||||
periodLumpSumMaxDrawdown: createPeriodAveragePricePattern(this, 'lump_sum_max_drawdown'),
|
||||
periodLumpSumMaxReturn: createPeriodAveragePricePattern(this, 'lump_sum_max_return'),
|
||||
periodLumpSumReturns: createPeriodAveragePricePattern(this, 'lump_sum_returns'),
|
||||
periodLumpSumStack: createPeriodLumpSumStackPattern(this, 'lump_sum_stack'),
|
||||
periodMaxDrawdown: createPeriodAveragePricePattern(this, 'dca_max_drawdown'),
|
||||
periodMaxReturn: createPeriodAveragePricePattern(this, 'dca_max_return'),
|
||||
periodReturns: createPeriodAveragePricePattern(this, 'dca_returns'),
|
||||
periodStack: createPeriodLumpSumStackPattern(this, 'dca_stack'),
|
||||
},
|
||||
|
||||
@@ -2054,24 +2054,6 @@ class PeriodLumpSumStackPattern:
|
||||
self._6y: _2015Pattern = _2015Pattern(client, _p('6y', acc))
|
||||
self._8y: _2015Pattern = _2015Pattern(client, _p('8y', acc))
|
||||
|
||||
class PeriodAveragePricePattern(Generic[T]):
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated metric name."""
|
||||
self._10y: MetricPattern4[T] = MetricPattern4(client, _p('10y', acc))
|
||||
self._1m: MetricPattern4[T] = MetricPattern4(client, _p('1m', acc))
|
||||
self._1w: MetricPattern4[T] = MetricPattern4(client, _p('1w', acc))
|
||||
self._1y: MetricPattern4[T] = MetricPattern4(client, _p('1y', acc))
|
||||
self._2y: MetricPattern4[T] = MetricPattern4(client, _p('2y', acc))
|
||||
self._3m: MetricPattern4[T] = MetricPattern4(client, _p('3m', acc))
|
||||
self._3y: MetricPattern4[T] = MetricPattern4(client, _p('3y', acc))
|
||||
self._4y: MetricPattern4[T] = MetricPattern4(client, _p('4y', acc))
|
||||
self._5y: MetricPattern4[T] = MetricPattern4(client, _p('5y', acc))
|
||||
self._6m: MetricPattern4[T] = MetricPattern4(client, _p('6m', acc))
|
||||
self._6y: MetricPattern4[T] = MetricPattern4(client, _p('6y', acc))
|
||||
self._8y: MetricPattern4[T] = MetricPattern4(client, _p('8y', acc))
|
||||
|
||||
class ClassAveragePricePattern(Generic[T]):
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
@@ -2090,6 +2072,24 @@ class ClassAveragePricePattern(Generic[T]):
|
||||
self._2025: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2025_average_price'))
|
||||
self._2026: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2026_average_price'))
|
||||
|
||||
class PeriodAveragePricePattern(Generic[T]):
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated metric name."""
|
||||
self._10y: MetricPattern4[T] = MetricPattern4(client, _p('10y', acc))
|
||||
self._1m: MetricPattern4[T] = MetricPattern4(client, _p('1m', acc))
|
||||
self._1w: MetricPattern4[T] = MetricPattern4(client, _p('1w', acc))
|
||||
self._1y: MetricPattern4[T] = MetricPattern4(client, _p('1y', acc))
|
||||
self._2y: MetricPattern4[T] = MetricPattern4(client, _p('2y', acc))
|
||||
self._3m: MetricPattern4[T] = MetricPattern4(client, _p('3m', acc))
|
||||
self._3y: MetricPattern4[T] = MetricPattern4(client, _p('3y', acc))
|
||||
self._4y: MetricPattern4[T] = MetricPattern4(client, _p('4y', acc))
|
||||
self._5y: MetricPattern4[T] = MetricPattern4(client, _p('5y', acc))
|
||||
self._6m: MetricPattern4[T] = MetricPattern4(client, _p('6m', acc))
|
||||
self._6y: MetricPattern4[T] = MetricPattern4(client, _p('6y', acc))
|
||||
self._8y: MetricPattern4[T] = MetricPattern4(client, _p('8y', acc))
|
||||
|
||||
class BitcoinPattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
@@ -2187,21 +2187,6 @@ class AddrCountPattern:
|
||||
self.p2wpkh: MetricPattern1[StoredU64] = MetricPattern1(client, _p('p2wpkh', acc))
|
||||
self.p2wsh: MetricPattern1[StoredU64] = MetricPattern1(client, _p('p2wsh', acc))
|
||||
|
||||
class FullnessPattern(Generic[T]):
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated metric name."""
|
||||
self.average: MetricPattern2[T] = MetricPattern2(client, _m(acc, 'average'))
|
||||
self.base: MetricPattern11[T] = MetricPattern11(client, acc)
|
||||
self.max: MetricPattern2[T] = MetricPattern2(client, _m(acc, 'max'))
|
||||
self.median: MetricPattern6[T] = MetricPattern6(client, _m(acc, 'median'))
|
||||
self.min: MetricPattern2[T] = MetricPattern2(client, _m(acc, 'min'))
|
||||
self.pct10: MetricPattern6[T] = MetricPattern6(client, _m(acc, 'pct10'))
|
||||
self.pct25: MetricPattern6[T] = MetricPattern6(client, _m(acc, 'pct25'))
|
||||
self.pct75: MetricPattern6[T] = MetricPattern6(client, _m(acc, 'pct75'))
|
||||
self.pct90: MetricPattern6[T] = MetricPattern6(client, _m(acc, 'pct90'))
|
||||
|
||||
class FeeRatePattern(Generic[T]):
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
@@ -2217,6 +2202,21 @@ class FeeRatePattern(Generic[T]):
|
||||
self.pct90: MetricPattern11[T] = MetricPattern11(client, _m(acc, 'pct90'))
|
||||
self.txindex: MetricPattern27[T] = MetricPattern27(client, acc)
|
||||
|
||||
class FullnessPattern(Generic[T]):
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated metric name."""
|
||||
self.average: MetricPattern2[T] = MetricPattern2(client, _m(acc, 'average'))
|
||||
self.base: MetricPattern11[T] = MetricPattern11(client, acc)
|
||||
self.max: MetricPattern2[T] = MetricPattern2(client, _m(acc, 'max'))
|
||||
self.median: MetricPattern6[T] = MetricPattern6(client, _m(acc, 'median'))
|
||||
self.min: MetricPattern2[T] = MetricPattern2(client, _m(acc, 'min'))
|
||||
self.pct10: MetricPattern6[T] = MetricPattern6(client, _m(acc, 'pct10'))
|
||||
self.pct25: MetricPattern6[T] = MetricPattern6(client, _m(acc, 'pct25'))
|
||||
self.pct75: MetricPattern6[T] = MetricPattern6(client, _m(acc, 'pct75'))
|
||||
self.pct90: MetricPattern6[T] = MetricPattern6(client, _m(acc, 'pct90'))
|
||||
|
||||
class _0satsPattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
@@ -2245,6 +2245,19 @@ class PhaseDailyCentsPattern(Generic[T]):
|
||||
self.pct75: MetricPattern6[T] = MetricPattern6(client, _m(acc, 'pct75'))
|
||||
self.pct90: MetricPattern6[T] = MetricPattern6(client, _m(acc, 'pct90'))
|
||||
|
||||
class _0satsPattern2:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated metric name."""
|
||||
self.activity: ActivityPattern2 = ActivityPattern2(client, acc)
|
||||
self.cost_basis: CostBasisPattern = CostBasisPattern(client, acc)
|
||||
self.outputs: OutputsPattern = OutputsPattern(client, _m(acc, 'utxo_count'))
|
||||
self.realized: RealizedPattern = RealizedPattern(client, acc)
|
||||
self.relative: RelativePattern4 = RelativePattern4(client, _m(acc, 'supply_in'))
|
||||
self.supply: SupplyPattern2 = SupplyPattern2(client, _m(acc, 'supply'))
|
||||
self.unrealized: UnrealizedPattern = UnrealizedPattern(client, acc)
|
||||
|
||||
class _100btcPattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
@@ -2271,19 +2284,6 @@ class PeriodCagrPattern:
|
||||
self._6y: MetricPattern4[StoredF32] = MetricPattern4(client, _p('6y', acc))
|
||||
self._8y: MetricPattern4[StoredF32] = MetricPattern4(client, _p('8y', acc))
|
||||
|
||||
class _0satsPattern2:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated metric name."""
|
||||
self.activity: ActivityPattern2 = ActivityPattern2(client, acc)
|
||||
self.cost_basis: CostBasisPattern = CostBasisPattern(client, acc)
|
||||
self.outputs: OutputsPattern = OutputsPattern(client, _m(acc, 'utxo_count'))
|
||||
self.realized: RealizedPattern = RealizedPattern(client, acc)
|
||||
self.relative: RelativePattern4 = RelativePattern4(client, _m(acc, 'supply_in'))
|
||||
self.supply: SupplyPattern2 = SupplyPattern2(client, _m(acc, 'supply'))
|
||||
self.unrealized: UnrealizedPattern = UnrealizedPattern(client, acc)
|
||||
|
||||
class _10yTo12yPattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
@@ -2297,6 +2297,19 @@ class _10yTo12yPattern:
|
||||
self.supply: SupplyPattern2 = SupplyPattern2(client, _m(acc, 'supply'))
|
||||
self.unrealized: UnrealizedPattern = UnrealizedPattern(client, acc)
|
||||
|
||||
class _10yPattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated metric name."""
|
||||
self.activity: ActivityPattern2 = ActivityPattern2(client, acc)
|
||||
self.cost_basis: CostBasisPattern = CostBasisPattern(client, acc)
|
||||
self.outputs: OutputsPattern = OutputsPattern(client, _m(acc, 'utxo_count'))
|
||||
self.realized: RealizedPattern4 = RealizedPattern4(client, acc)
|
||||
self.relative: RelativePattern = RelativePattern(client, acc)
|
||||
self.supply: SupplyPattern2 = SupplyPattern2(client, _m(acc, 'supply'))
|
||||
self.unrealized: UnrealizedPattern = UnrealizedPattern(client, acc)
|
||||
|
||||
class UnrealizedPattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
@@ -2310,19 +2323,6 @@ class UnrealizedPattern:
|
||||
self.unrealized_loss: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'unrealized_loss'))
|
||||
self.unrealized_profit: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'unrealized_profit'))
|
||||
|
||||
class _10yPattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated metric name."""
|
||||
self.activity: ActivityPattern2 = ActivityPattern2(client, acc)
|
||||
self.cost_basis: CostBasisPattern = CostBasisPattern(client, acc)
|
||||
self.outputs: OutputsPattern = OutputsPattern(client, _m(acc, 'utxo_count'))
|
||||
self.realized: RealizedPattern4 = RealizedPattern4(client, acc)
|
||||
self.relative: RelativePattern = RelativePattern(client, acc)
|
||||
self.supply: SupplyPattern2 = SupplyPattern2(client, _m(acc, 'supply'))
|
||||
self.unrealized: UnrealizedPattern = UnrealizedPattern(client, acc)
|
||||
|
||||
class ActivityPattern2:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
@@ -2353,24 +2353,6 @@ class CostBasisPattern2:
|
||||
self.min: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'min_cost_basis'))
|
||||
self.percentiles: PercentilesPattern = PercentilesPattern(client, _m(acc, 'cost_basis'))
|
||||
|
||||
class CoinbasePattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated metric name."""
|
||||
self.bitcoin: BitcoinPattern = BitcoinPattern(client, _m(acc, 'btc'))
|
||||
self.dollars: DollarsPattern[Dollars] = DollarsPattern(client, _m(acc, 'usd'))
|
||||
self.sats: DollarsPattern[Sats] = DollarsPattern(client, acc)
|
||||
|
||||
class CoinbasePattern2:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated metric name."""
|
||||
self.bitcoin: BlockCountPattern[Bitcoin] = BlockCountPattern(client, _m(acc, 'btc'))
|
||||
self.dollars: BlockCountPattern[Dollars] = BlockCountPattern(client, _m(acc, 'usd'))
|
||||
self.sats: BlockCountPattern[Sats] = BlockCountPattern(client, acc)
|
||||
|
||||
class ActiveSupplyPattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
@@ -2389,6 +2371,15 @@ class SegwitAdoptionPattern:
|
||||
self.cumulative: MetricPattern2[StoredF32] = MetricPattern2(client, _m(acc, 'cumulative'))
|
||||
self.sum: MetricPattern2[StoredF32] = MetricPattern2(client, _m(acc, 'sum'))
|
||||
|
||||
class CoinbasePattern2:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated metric name."""
|
||||
self.bitcoin: BlockCountPattern[Bitcoin] = BlockCountPattern(client, _m(acc, 'btc'))
|
||||
self.dollars: BlockCountPattern[Dollars] = BlockCountPattern(client, _m(acc, 'usd'))
|
||||
self.sats: BlockCountPattern[Sats] = BlockCountPattern(client, acc)
|
||||
|
||||
class UnclaimedRewardsPattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
@@ -2398,6 +2389,15 @@ class UnclaimedRewardsPattern:
|
||||
self.dollars: BlockCountPattern[Dollars] = BlockCountPattern(client, _m(acc, 'usd'))
|
||||
self.sats: BlockCountPattern[Sats] = BlockCountPattern(client, acc)
|
||||
|
||||
class CoinbasePattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated metric name."""
|
||||
self.bitcoin: BitcoinPattern = BitcoinPattern(client, _m(acc, 'btc'))
|
||||
self.dollars: DollarsPattern[Dollars] = DollarsPattern(client, _m(acc, 'usd'))
|
||||
self.sats: DollarsPattern[Sats] = DollarsPattern(client, acc)
|
||||
|
||||
class _2015Pattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
@@ -2407,14 +2407,6 @@ class _2015Pattern:
|
||||
self.dollars: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'usd'))
|
||||
self.sats: MetricPattern4[Sats] = MetricPattern4(client, acc)
|
||||
|
||||
class SupplyPattern2:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated metric name."""
|
||||
self.halved: ActiveSupplyPattern = ActiveSupplyPattern(client, _m(acc, 'halved'))
|
||||
self.total: ActiveSupplyPattern = ActiveSupplyPattern(client, acc)
|
||||
|
||||
class RelativePattern4:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
@@ -2423,6 +2415,14 @@ class RelativePattern4:
|
||||
self.supply_in_loss_rel_to_own_supply: MetricPattern1[StoredF64] = MetricPattern1(client, _m(acc, 'loss_rel_to_own_supply'))
|
||||
self.supply_in_profit_rel_to_own_supply: MetricPattern1[StoredF64] = MetricPattern1(client, _m(acc, 'profit_rel_to_own_supply'))
|
||||
|
||||
class SupplyPattern2:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated metric name."""
|
||||
self.halved: ActiveSupplyPattern = ActiveSupplyPattern(client, _m(acc, 'halved'))
|
||||
self.total: ActiveSupplyPattern = ActiveSupplyPattern(client, acc)
|
||||
|
||||
class CostBasisPattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
@@ -3320,6 +3320,74 @@ class MetricsTree_Market_Ath:
|
||||
self.price_drawdown: MetricPattern3[StoredF32] = MetricPattern3(client, 'price_drawdown')
|
||||
self.years_since_price_ath: MetricPattern4[StoredF32] = MetricPattern4(client, 'years_since_price_ath')
|
||||
|
||||
class MetricsTree_Market_Dca_ClassDaysInLoss:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self._2015: MetricPattern4[StoredU32] = MetricPattern4(client, 'dca_class_2015_days_in_loss')
|
||||
self._2016: MetricPattern4[StoredU32] = MetricPattern4(client, 'dca_class_2016_days_in_loss')
|
||||
self._2017: MetricPattern4[StoredU32] = MetricPattern4(client, 'dca_class_2017_days_in_loss')
|
||||
self._2018: MetricPattern4[StoredU32] = MetricPattern4(client, 'dca_class_2018_days_in_loss')
|
||||
self._2019: MetricPattern4[StoredU32] = MetricPattern4(client, 'dca_class_2019_days_in_loss')
|
||||
self._2020: MetricPattern4[StoredU32] = MetricPattern4(client, 'dca_class_2020_days_in_loss')
|
||||
self._2021: MetricPattern4[StoredU32] = MetricPattern4(client, 'dca_class_2021_days_in_loss')
|
||||
self._2022: MetricPattern4[StoredU32] = MetricPattern4(client, 'dca_class_2022_days_in_loss')
|
||||
self._2023: MetricPattern4[StoredU32] = MetricPattern4(client, 'dca_class_2023_days_in_loss')
|
||||
self._2024: MetricPattern4[StoredU32] = MetricPattern4(client, 'dca_class_2024_days_in_loss')
|
||||
self._2025: MetricPattern4[StoredU32] = MetricPattern4(client, 'dca_class_2025_days_in_loss')
|
||||
self._2026: MetricPattern4[StoredU32] = MetricPattern4(client, 'dca_class_2026_days_in_loss')
|
||||
|
||||
class MetricsTree_Market_Dca_ClassDaysInProfit:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self._2015: MetricPattern4[StoredU32] = MetricPattern4(client, 'dca_class_2015_days_in_profit')
|
||||
self._2016: MetricPattern4[StoredU32] = MetricPattern4(client, 'dca_class_2016_days_in_profit')
|
||||
self._2017: MetricPattern4[StoredU32] = MetricPattern4(client, 'dca_class_2017_days_in_profit')
|
||||
self._2018: MetricPattern4[StoredU32] = MetricPattern4(client, 'dca_class_2018_days_in_profit')
|
||||
self._2019: MetricPattern4[StoredU32] = MetricPattern4(client, 'dca_class_2019_days_in_profit')
|
||||
self._2020: MetricPattern4[StoredU32] = MetricPattern4(client, 'dca_class_2020_days_in_profit')
|
||||
self._2021: MetricPattern4[StoredU32] = MetricPattern4(client, 'dca_class_2021_days_in_profit')
|
||||
self._2022: MetricPattern4[StoredU32] = MetricPattern4(client, 'dca_class_2022_days_in_profit')
|
||||
self._2023: MetricPattern4[StoredU32] = MetricPattern4(client, 'dca_class_2023_days_in_profit')
|
||||
self._2024: MetricPattern4[StoredU32] = MetricPattern4(client, 'dca_class_2024_days_in_profit')
|
||||
self._2025: MetricPattern4[StoredU32] = MetricPattern4(client, 'dca_class_2025_days_in_profit')
|
||||
self._2026: MetricPattern4[StoredU32] = MetricPattern4(client, 'dca_class_2026_days_in_profit')
|
||||
|
||||
class MetricsTree_Market_Dca_ClassMaxDrawdown:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self._2015: MetricPattern4[StoredF32] = MetricPattern4(client, 'dca_class_2015_max_drawdown')
|
||||
self._2016: MetricPattern4[StoredF32] = MetricPattern4(client, 'dca_class_2016_max_drawdown')
|
||||
self._2017: MetricPattern4[StoredF32] = MetricPattern4(client, 'dca_class_2017_max_drawdown')
|
||||
self._2018: MetricPattern4[StoredF32] = MetricPattern4(client, 'dca_class_2018_max_drawdown')
|
||||
self._2019: MetricPattern4[StoredF32] = MetricPattern4(client, 'dca_class_2019_max_drawdown')
|
||||
self._2020: MetricPattern4[StoredF32] = MetricPattern4(client, 'dca_class_2020_max_drawdown')
|
||||
self._2021: MetricPattern4[StoredF32] = MetricPattern4(client, 'dca_class_2021_max_drawdown')
|
||||
self._2022: MetricPattern4[StoredF32] = MetricPattern4(client, 'dca_class_2022_max_drawdown')
|
||||
self._2023: MetricPattern4[StoredF32] = MetricPattern4(client, 'dca_class_2023_max_drawdown')
|
||||
self._2024: MetricPattern4[StoredF32] = MetricPattern4(client, 'dca_class_2024_max_drawdown')
|
||||
self._2025: MetricPattern4[StoredF32] = MetricPattern4(client, 'dca_class_2025_max_drawdown')
|
||||
self._2026: MetricPattern4[StoredF32] = MetricPattern4(client, 'dca_class_2026_max_drawdown')
|
||||
|
||||
class MetricsTree_Market_Dca_ClassMaxReturn:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self._2015: MetricPattern4[StoredF32] = MetricPattern4(client, 'dca_class_2015_max_return')
|
||||
self._2016: MetricPattern4[StoredF32] = MetricPattern4(client, 'dca_class_2016_max_return')
|
||||
self._2017: MetricPattern4[StoredF32] = MetricPattern4(client, 'dca_class_2017_max_return')
|
||||
self._2018: MetricPattern4[StoredF32] = MetricPattern4(client, 'dca_class_2018_max_return')
|
||||
self._2019: MetricPattern4[StoredF32] = MetricPattern4(client, 'dca_class_2019_max_return')
|
||||
self._2020: MetricPattern4[StoredF32] = MetricPattern4(client, 'dca_class_2020_max_return')
|
||||
self._2021: MetricPattern4[StoredF32] = MetricPattern4(client, 'dca_class_2021_max_return')
|
||||
self._2022: MetricPattern4[StoredF32] = MetricPattern4(client, 'dca_class_2022_max_return')
|
||||
self._2023: MetricPattern4[StoredF32] = MetricPattern4(client, 'dca_class_2023_max_return')
|
||||
self._2024: MetricPattern4[StoredF32] = MetricPattern4(client, 'dca_class_2024_max_return')
|
||||
self._2025: MetricPattern4[StoredF32] = MetricPattern4(client, 'dca_class_2025_max_return')
|
||||
self._2026: MetricPattern4[StoredF32] = MetricPattern4(client, 'dca_class_2026_max_return')
|
||||
|
||||
class MetricsTree_Market_Dca_ClassReturns:
|
||||
"""Metrics tree node."""
|
||||
|
||||
@@ -3359,11 +3427,24 @@ class MetricsTree_Market_Dca:
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self.class_average_price: ClassAveragePricePattern[Dollars] = ClassAveragePricePattern(client, 'dca_class')
|
||||
self.class_days_in_loss: MetricsTree_Market_Dca_ClassDaysInLoss = MetricsTree_Market_Dca_ClassDaysInLoss(client)
|
||||
self.class_days_in_profit: MetricsTree_Market_Dca_ClassDaysInProfit = MetricsTree_Market_Dca_ClassDaysInProfit(client)
|
||||
self.class_max_drawdown: MetricsTree_Market_Dca_ClassMaxDrawdown = MetricsTree_Market_Dca_ClassMaxDrawdown(client)
|
||||
self.class_max_return: MetricsTree_Market_Dca_ClassMaxReturn = MetricsTree_Market_Dca_ClassMaxReturn(client)
|
||||
self.class_returns: MetricsTree_Market_Dca_ClassReturns = MetricsTree_Market_Dca_ClassReturns(client)
|
||||
self.class_stack: MetricsTree_Market_Dca_ClassStack = MetricsTree_Market_Dca_ClassStack(client)
|
||||
self.period_average_price: PeriodAveragePricePattern[Dollars] = PeriodAveragePricePattern(client, 'dca_average_price')
|
||||
self.period_cagr: PeriodCagrPattern = PeriodCagrPattern(client, 'dca_cagr')
|
||||
self.period_days_in_loss: PeriodAveragePricePattern[StoredU32] = PeriodAveragePricePattern(client, 'dca_days_in_loss')
|
||||
self.period_days_in_profit: PeriodAveragePricePattern[StoredU32] = PeriodAveragePricePattern(client, 'dca_days_in_profit')
|
||||
self.period_lump_sum_days_in_loss: PeriodAveragePricePattern[StoredU32] = PeriodAveragePricePattern(client, 'lump_sum_days_in_loss')
|
||||
self.period_lump_sum_days_in_profit: PeriodAveragePricePattern[StoredU32] = PeriodAveragePricePattern(client, 'lump_sum_days_in_profit')
|
||||
self.period_lump_sum_max_drawdown: PeriodAveragePricePattern[StoredF32] = PeriodAveragePricePattern(client, 'lump_sum_max_drawdown')
|
||||
self.period_lump_sum_max_return: PeriodAveragePricePattern[StoredF32] = PeriodAveragePricePattern(client, 'lump_sum_max_return')
|
||||
self.period_lump_sum_returns: PeriodAveragePricePattern[StoredF32] = PeriodAveragePricePattern(client, 'lump_sum_returns')
|
||||
self.period_lump_sum_stack: PeriodLumpSumStackPattern = PeriodLumpSumStackPattern(client, 'lump_sum_stack')
|
||||
self.period_max_drawdown: PeriodAveragePricePattern[StoredF32] = PeriodAveragePricePattern(client, 'dca_max_drawdown')
|
||||
self.period_max_return: PeriodAveragePricePattern[StoredF32] = PeriodAveragePricePattern(client, 'dca_max_return')
|
||||
self.period_returns: PeriodAveragePricePattern[StoredF32] = PeriodAveragePricePattern(client, 'dca_returns')
|
||||
self.period_stack: PeriodLumpSumStackPattern = PeriodLumpSumStackPattern(client, 'dca_stack')
|
||||
|
||||
|
||||
@@ -161,6 +161,7 @@ export function createChart({ parent, id: chartId, brk, fitContent }) {
|
||||
/** @satisfies {DeepPartial<ChartOptions>} */ ({
|
||||
autoSize: true,
|
||||
layout: {
|
||||
// fontSize: 14,
|
||||
fontFamily: style.fontFamily,
|
||||
background: { color: "transparent" },
|
||||
attributionLogo: false,
|
||||
|
||||
@@ -30,7 +30,6 @@ export function createChainSection(ctx) {
|
||||
pools,
|
||||
inputs,
|
||||
outputs,
|
||||
market,
|
||||
scripts,
|
||||
supply,
|
||||
distribution,
|
||||
@@ -381,17 +380,22 @@ export function createChainSection(ctx) {
|
||||
],
|
||||
},
|
||||
|
||||
// Input
|
||||
// UTXO Set (merged Input, Output, UTXO)
|
||||
{
|
||||
name: "Input",
|
||||
name: "UTXO Set",
|
||||
tree: [
|
||||
{
|
||||
name: "Count",
|
||||
name: "Input Count",
|
||||
title: "Input Count",
|
||||
bottom: [...fromSizePattern(inputs.count, Unit.count)],
|
||||
},
|
||||
{
|
||||
name: "Speed",
|
||||
name: "Output Count",
|
||||
title: "Output Count",
|
||||
bottom: [...fromSizePattern(outputs.count.totalCount, Unit.count)],
|
||||
},
|
||||
{
|
||||
name: "Inputs/sec",
|
||||
title: "Inputs Per Second",
|
||||
bottom: [
|
||||
dots({
|
||||
@@ -401,20 +405,8 @@ export function createChainSection(ctx) {
|
||||
}),
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// Output
|
||||
{
|
||||
name: "Output",
|
||||
tree: [
|
||||
{
|
||||
name: "Count",
|
||||
title: "Output Count",
|
||||
bottom: [...fromSizePattern(outputs.count.totalCount, Unit.count)],
|
||||
},
|
||||
{
|
||||
name: "Speed",
|
||||
name: "Outputs/sec",
|
||||
title: "Outputs Per Second",
|
||||
bottom: [
|
||||
dots({
|
||||
@@ -424,14 +416,8 @@ export function createChainSection(ctx) {
|
||||
}),
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
{
|
||||
name: "UTXO",
|
||||
tree: [
|
||||
{
|
||||
name: "Count",
|
||||
name: "UTXO Count",
|
||||
title: "UTXO Count",
|
||||
bottom: [
|
||||
line({
|
||||
@@ -451,19 +437,49 @@ export function createChainSection(ctx) {
|
||||
{
|
||||
name: "Count",
|
||||
tree: [
|
||||
{ name: "P2PKH", title: "P2PKH Output Count", bottom: fromDollarsPattern(scripts.count.p2pkh, Unit.count) },
|
||||
{ name: "P2SH", title: "P2SH Output Count", bottom: fromDollarsPattern(scripts.count.p2sh, Unit.count) },
|
||||
{ name: "P2WPKH", title: "P2WPKH Output Count", bottom: fromDollarsPattern(scripts.count.p2wpkh, Unit.count) },
|
||||
{ name: "P2WSH", title: "P2WSH Output Count", bottom: fromDollarsPattern(scripts.count.p2wsh, Unit.count) },
|
||||
{ name: "P2TR", title: "P2TR Output Count", bottom: fromDollarsPattern(scripts.count.p2tr, Unit.count) },
|
||||
{ name: "P2PK33", title: "P2PK33 Output Count", bottom: fromDollarsPattern(scripts.count.p2pk33, Unit.count) },
|
||||
{ name: "P2PK65", title: "P2PK65 Output Count", bottom: fromDollarsPattern(scripts.count.p2pk65, Unit.count) },
|
||||
{ name: "P2MS", title: "P2MS Output Count", bottom: fromDollarsPattern(scripts.count.p2ms, Unit.count) },
|
||||
{ name: "P2A", title: "P2A Output Count", bottom: fromDollarsPattern(scripts.count.p2a, Unit.count) },
|
||||
{ name: "OP_RETURN", title: "OP_RETURN Output Count", bottom: fromDollarsPattern(scripts.count.opreturn, Unit.count) },
|
||||
{ name: "SegWit", title: "SegWit Output Count", bottom: fromDollarsPattern(scripts.count.segwit, Unit.count) },
|
||||
{ name: "Empty", title: "Empty Output Count", bottom: fromDollarsPattern(scripts.count.emptyoutput, Unit.count) },
|
||||
{ name: "Unknown", title: "Unknown Output Count", bottom: fromDollarsPattern(scripts.count.unknownoutput, Unit.count) },
|
||||
// Legacy scripts
|
||||
{
|
||||
name: "Legacy",
|
||||
tree: [
|
||||
{ name: "P2PKH", title: "P2PKH Output Count", bottom: fromDollarsPattern(scripts.count.p2pkh, Unit.count) },
|
||||
{ name: "P2PK33", title: "P2PK33 Output Count", bottom: fromDollarsPattern(scripts.count.p2pk33, Unit.count) },
|
||||
{ name: "P2PK65", title: "P2PK65 Output Count", bottom: fromDollarsPattern(scripts.count.p2pk65, Unit.count) },
|
||||
],
|
||||
},
|
||||
// Script Hash
|
||||
{
|
||||
name: "Script Hash",
|
||||
tree: [
|
||||
{ name: "P2SH", title: "P2SH Output Count", bottom: fromDollarsPattern(scripts.count.p2sh, Unit.count) },
|
||||
{ name: "P2MS", title: "P2MS Output Count", bottom: fromDollarsPattern(scripts.count.p2ms, Unit.count) },
|
||||
],
|
||||
},
|
||||
// SegWit scripts
|
||||
{
|
||||
name: "SegWit",
|
||||
tree: [
|
||||
{ name: "All SegWit", title: "SegWit Output Count", bottom: fromDollarsPattern(scripts.count.segwit, Unit.count) },
|
||||
{ name: "P2WPKH", title: "P2WPKH Output Count", bottom: fromDollarsPattern(scripts.count.p2wpkh, Unit.count) },
|
||||
{ name: "P2WSH", title: "P2WSH Output Count", bottom: fromDollarsPattern(scripts.count.p2wsh, Unit.count) },
|
||||
],
|
||||
},
|
||||
// Taproot scripts
|
||||
{
|
||||
name: "Taproot",
|
||||
tree: [
|
||||
{ name: "P2TR", title: "P2TR Output Count", bottom: fromDollarsPattern(scripts.count.p2tr, Unit.count) },
|
||||
{ name: "P2A", title: "P2A Output Count", bottom: fromDollarsPattern(scripts.count.p2a, Unit.count) },
|
||||
],
|
||||
},
|
||||
// Other scripts
|
||||
{
|
||||
name: "Other",
|
||||
tree: [
|
||||
{ name: "OP_RETURN", title: "OP_RETURN Output Count", bottom: fromDollarsPattern(scripts.count.opreturn, Unit.count) },
|
||||
{ name: "Empty", title: "Empty Output Count", bottom: fromDollarsPattern(scripts.count.emptyoutput, Unit.count) },
|
||||
{ name: "Unknown", title: "Unknown Output Count", bottom: fromDollarsPattern(scripts.count.unknownoutput, Unit.count) },
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -489,12 +505,7 @@ export function createChainSection(ctx) {
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Value",
|
||||
tree: [
|
||||
{ name: "OP_RETURN", title: "OP_RETURN Value", bottom: fromCoinbasePattern(scripts.value.opreturn) },
|
||||
],
|
||||
},
|
||||
{ name: "OP_RETURN Value", title: "OP_RETURN Value", bottom: fromCoinbasePattern(scripts.value.opreturn) },
|
||||
],
|
||||
},
|
||||
|
||||
@@ -925,18 +936,6 @@ export function createChainSection(ctx) {
|
||||
}),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Puell Multiple",
|
||||
title: "Puell Multiple",
|
||||
bottom: [
|
||||
baseline({
|
||||
metric: market.indicators.puellMultiple,
|
||||
name: "Puell Multiple",
|
||||
unit: Unit.ratio,
|
||||
base: 1,
|
||||
}),
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ function createCointimePriceWithRatioOptions(
|
||||
) {
|
||||
return [
|
||||
{
|
||||
name: "price",
|
||||
name: "Price",
|
||||
title,
|
||||
top: [line({ metric: price, name: legend, color, unit: Unit.usd })],
|
||||
},
|
||||
@@ -78,7 +78,7 @@ export function createCointimeSection(ctx) {
|
||||
{
|
||||
price: pricing.cointimePrice,
|
||||
ratio: pricing.cointimePriceRatio,
|
||||
name: "cointime",
|
||||
name: "Cointime",
|
||||
title: "Cointime Price",
|
||||
color: colors.yellow,
|
||||
},
|
||||
@@ -88,31 +88,31 @@ export function createCointimeSection(ctx) {
|
||||
const cointimeCapitalizations = [
|
||||
{
|
||||
metric: cap.vaultedCap,
|
||||
name: "vaulted",
|
||||
name: "Vaulted",
|
||||
title: "Vaulted Cap",
|
||||
color: colors.lime,
|
||||
},
|
||||
{
|
||||
metric: cap.activeCap,
|
||||
name: "active",
|
||||
name: "Active",
|
||||
title: "Active Cap",
|
||||
color: colors.rose,
|
||||
},
|
||||
{
|
||||
metric: cap.cointimeCap,
|
||||
name: "cointime",
|
||||
name: "Cointime",
|
||||
title: "Cointime Cap",
|
||||
color: colors.yellow,
|
||||
},
|
||||
{
|
||||
metric: cap.investorCap,
|
||||
name: "investor",
|
||||
name: "Investor",
|
||||
title: "Investor Cap",
|
||||
color: colors.fuchsia,
|
||||
},
|
||||
{
|
||||
metric: cap.thermoCap,
|
||||
name: "thermo",
|
||||
name: "Thermo",
|
||||
title: "Thermo Cap",
|
||||
color: colors.emerald,
|
||||
},
|
||||
@@ -283,7 +283,7 @@ export function createCointimeSection(ctx) {
|
||||
name: "Reserve Risk",
|
||||
tree: [
|
||||
{
|
||||
name: "reserve risk",
|
||||
name: "Ratio",
|
||||
title: "Reserve Risk",
|
||||
bottom: [
|
||||
line({
|
||||
@@ -295,7 +295,7 @@ export function createCointimeSection(ctx) {
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "hodl bank",
|
||||
name: "HODL Bank",
|
||||
title: "HODL Bank",
|
||||
bottom: [
|
||||
line({
|
||||
@@ -307,7 +307,7 @@ export function createCointimeSection(ctx) {
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "vocdd 365d sma",
|
||||
name: "VOCDD 365d SMA",
|
||||
title: "VOCDD 365d SMA",
|
||||
bottom: [
|
||||
line({
|
||||
@@ -326,7 +326,7 @@ export function createCointimeSection(ctx) {
|
||||
name: "Value",
|
||||
tree: [
|
||||
{
|
||||
name: "created",
|
||||
name: "Created",
|
||||
title: "Cointime Value Created",
|
||||
bottom: [
|
||||
line({
|
||||
@@ -345,7 +345,7 @@ export function createCointimeSection(ctx) {
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "destroyed",
|
||||
name: "Destroyed",
|
||||
title: "Cointime Value Destroyed",
|
||||
bottom: [
|
||||
line({
|
||||
@@ -364,7 +364,7 @@ export function createCointimeSection(ctx) {
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "stored",
|
||||
name: "Stored",
|
||||
title: "Cointime Value Stored",
|
||||
bottom: [
|
||||
line({
|
||||
@@ -383,7 +383,7 @@ export function createCointimeSection(ctx) {
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "vocdd",
|
||||
name: "VOCDD",
|
||||
title: "VOCDD (Value of Coin Days Destroyed)",
|
||||
bottom: [
|
||||
line({
|
||||
|
||||
@@ -18,8 +18,6 @@ import {
|
||||
createSingleCoinsDestroyedSeries,
|
||||
createGroupedCoinblocksDestroyedSeries,
|
||||
createGroupedCoindaysDestroyedSeries,
|
||||
createGroupedSatblocksDestroyedSeries,
|
||||
createGroupedSatdaysDestroyedSeries,
|
||||
createSingleSentSeries,
|
||||
createGroupedSentSatsSeries,
|
||||
createGroupedSentBitcoinSeries,
|
||||
@@ -48,7 +46,7 @@ export function createAddressCohortFolder(ctx, args) {
|
||||
// Supply section
|
||||
isSingle
|
||||
? {
|
||||
name: "supply",
|
||||
name: "Supply",
|
||||
title: title("Supply"),
|
||||
bottom: createSingleSupplySeries(
|
||||
ctx,
|
||||
@@ -60,14 +58,14 @@ export function createAddressCohortFolder(ctx, args) {
|
||||
|
||||
// UTXO count
|
||||
{
|
||||
name: "utxo count",
|
||||
name: "UTXO Count",
|
||||
title: title("UTXO Count"),
|
||||
bottom: createUtxoCountSeries(list, useGroupName),
|
||||
},
|
||||
|
||||
// Address count (ADDRESS COHORTS ONLY - fully type safe!)
|
||||
{
|
||||
name: "address count",
|
||||
name: "Address Count",
|
||||
title: title("Address Count"),
|
||||
bottom: createAddressCountSeries(ctx, list, useGroupName),
|
||||
},
|
||||
@@ -94,12 +92,12 @@ export function createAddressCohortFolder(ctx, args) {
|
||||
title,
|
||||
)),
|
||||
{
|
||||
name: "capitalization",
|
||||
name: "Capitalization",
|
||||
title: title("Realized Cap"),
|
||||
bottom: createRealizedCapWithExtras(ctx, list, args, useGroupName),
|
||||
},
|
||||
{
|
||||
name: "value",
|
||||
name: "Value",
|
||||
title: title("Realized Value"),
|
||||
bottom: list.map(({ color, name, tree }) =>
|
||||
line({
|
||||
@@ -143,7 +141,7 @@ function createRealizedPriceOptions(args, title) {
|
||||
|
||||
return [
|
||||
{
|
||||
name: "price",
|
||||
name: "Price",
|
||||
title: title("Realized Price"),
|
||||
top: [
|
||||
line({
|
||||
@@ -179,7 +177,7 @@ function createRealizedCapWithExtras(ctx, list, args, useGroupName) {
|
||||
? [
|
||||
baseline({
|
||||
metric: tree.realized.realizedCap30dDelta,
|
||||
name: "30d Change",
|
||||
name: "1m Change",
|
||||
unit: Unit.usd,
|
||||
defaultActive: false,
|
||||
}),
|
||||
@@ -203,7 +201,7 @@ function createRealizedPnlSection(ctx, args, title) {
|
||||
|
||||
return [
|
||||
{
|
||||
name: "pnl",
|
||||
name: "P&L",
|
||||
title: title("Realized P&L"),
|
||||
bottom: [
|
||||
line({
|
||||
@@ -297,7 +295,7 @@ function createRealizedPnlSection(ctx, args, title) {
|
||||
}),
|
||||
baseline({
|
||||
metric: realized.netRealizedPnlCumulative30dDelta,
|
||||
name: "Cumulative 30d change",
|
||||
name: "Cumulative 1m Change",
|
||||
unit: Unit.usd,
|
||||
defaultActive: false,
|
||||
}),
|
||||
@@ -314,13 +312,13 @@ function createRealizedPnlSection(ctx, args, title) {
|
||||
}),
|
||||
baseline({
|
||||
metric: realized.netRealizedPnlCumulative30dDeltaRelToRealizedCap,
|
||||
name: "Cumulative 30d change",
|
||||
name: "Cumulative 1m Change",
|
||||
unit: Unit.pctRcap,
|
||||
defaultActive: false,
|
||||
}),
|
||||
baseline({
|
||||
metric: realized.netRealizedPnlCumulative30dDeltaRelToMarketCap,
|
||||
name: "Cumulative 30d change",
|
||||
name: "Cumulative 1m Change",
|
||||
unit: Unit.pctMcap,
|
||||
}),
|
||||
priceLine({
|
||||
@@ -339,7 +337,7 @@ function createRealizedPnlSection(ctx, args, title) {
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "sopr",
|
||||
name: "SOPR",
|
||||
title: title("SOPR"),
|
||||
bottom: [
|
||||
baseline({
|
||||
@@ -398,7 +396,7 @@ function createRealizedPnlSection(ctx, args, title) {
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "value",
|
||||
name: "Value",
|
||||
title: title("Value Created & Destroyed"),
|
||||
bottom: [
|
||||
line({
|
||||
@@ -434,7 +432,7 @@ function createUnrealizedSection(ctx, list, useGroupName, title) {
|
||||
name: "Unrealized",
|
||||
tree: [
|
||||
{
|
||||
name: "profit",
|
||||
name: "Profit",
|
||||
title: title("Unrealized Profit"),
|
||||
bottom: list.flatMap(({ color, name, tree }) => [
|
||||
line({
|
||||
@@ -446,7 +444,7 @@ function createUnrealizedSection(ctx, list, useGroupName, title) {
|
||||
]),
|
||||
},
|
||||
{
|
||||
name: "loss",
|
||||
name: "Loss",
|
||||
title: title("Unrealized Loss"),
|
||||
bottom: list.flatMap(({ color, name, tree }) => [
|
||||
line({
|
||||
@@ -458,7 +456,7 @@ function createUnrealizedSection(ctx, list, useGroupName, title) {
|
||||
]),
|
||||
},
|
||||
{
|
||||
name: "total pnl",
|
||||
name: "Total P&L",
|
||||
title: title("Total Unrealized P&L"),
|
||||
bottom: list.flatMap(({ color, name, tree }) => [
|
||||
baseline({
|
||||
@@ -470,7 +468,7 @@ function createUnrealizedSection(ctx, list, useGroupName, title) {
|
||||
]),
|
||||
},
|
||||
{
|
||||
name: "negative loss",
|
||||
name: "Negative Loss",
|
||||
title: title("Negative Unrealized Loss"),
|
||||
bottom: list.flatMap(({ color, name, tree }) => [
|
||||
line({
|
||||
@@ -485,7 +483,7 @@ function createUnrealizedSection(ctx, list, useGroupName, title) {
|
||||
name: "Relative",
|
||||
tree: [
|
||||
{
|
||||
name: "nupl",
|
||||
name: "NUPL",
|
||||
title: title("NUPL (Rel to Market Cap)"),
|
||||
bottom: list.flatMap(({ color, name, tree }) => [
|
||||
baseline({
|
||||
@@ -498,7 +496,7 @@ function createUnrealizedSection(ctx, list, useGroupName, title) {
|
||||
]),
|
||||
},
|
||||
{
|
||||
name: "profit",
|
||||
name: "Profit",
|
||||
title: title("Unrealized Profit (% of Market Cap)"),
|
||||
bottom: list.flatMap(({ color, name, tree }) => [
|
||||
line({
|
||||
@@ -510,7 +508,7 @@ function createUnrealizedSection(ctx, list, useGroupName, title) {
|
||||
]),
|
||||
},
|
||||
{
|
||||
name: "loss",
|
||||
name: "Loss",
|
||||
title: title("Unrealized Loss (% of Market Cap)"),
|
||||
bottom: list.flatMap(({ color, name, tree }) => [
|
||||
line({
|
||||
@@ -522,7 +520,7 @@ function createUnrealizedSection(ctx, list, useGroupName, title) {
|
||||
]),
|
||||
},
|
||||
{
|
||||
name: "net pnl",
|
||||
name: "Net P&L",
|
||||
title: title("Net Unrealized P&L (% of Market Cap)"),
|
||||
bottom: list.flatMap(({ color, name, tree }) => [
|
||||
baseline({
|
||||
@@ -534,7 +532,7 @@ function createUnrealizedSection(ctx, list, useGroupName, title) {
|
||||
]),
|
||||
},
|
||||
{
|
||||
name: "negative loss",
|
||||
name: "Negative Loss",
|
||||
title: title("Negative Unrealized Loss (% of Market Cap)"),
|
||||
bottom: list.flatMap(({ color, name, tree }) => [
|
||||
line({
|
||||
@@ -548,7 +546,7 @@ function createUnrealizedSection(ctx, list, useGroupName, title) {
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "nupl",
|
||||
name: "NUPL",
|
||||
title: title("Net Unrealized P&L"),
|
||||
bottom: list.flatMap(({ color, name, tree }) => [
|
||||
baseline({
|
||||
@@ -581,7 +579,7 @@ function createCostBasisSection(list, useGroupName, title) {
|
||||
name: "Cost Basis",
|
||||
tree: [
|
||||
{
|
||||
name: "min",
|
||||
name: "Min",
|
||||
title: title("Min Cost Basis"),
|
||||
top: list.map(({ color, name, tree }) =>
|
||||
line({
|
||||
@@ -656,16 +654,6 @@ function createActivitySection(args, title) {
|
||||
title: title("Coindays Destroyed"),
|
||||
bottom: createGroupedCoindaysDestroyedSeries(list),
|
||||
},
|
||||
{
|
||||
name: "satblocks destroyed",
|
||||
title: title("Satblocks Destroyed"),
|
||||
bottom: createGroupedSatblocksDestroyedSeries(list),
|
||||
},
|
||||
{
|
||||
name: "satdays destroyed",
|
||||
title: title("Satdays Destroyed"),
|
||||
bottom: createGroupedSatdaysDestroyedSeries(list),
|
||||
},
|
||||
{
|
||||
name: "Sent",
|
||||
tree: [
|
||||
|
||||
@@ -109,20 +109,20 @@ export function createGroupedSupplyInLossSeries(list, { relativeMetrics } = {})
|
||||
*/
|
||||
export function createGroupedSupplySection(list, title, { supplyRelativeMetrics, profitRelativeMetrics, lossRelativeMetrics } = {}) {
|
||||
return {
|
||||
name: "supply",
|
||||
name: "Supply",
|
||||
tree: [
|
||||
{
|
||||
name: "total",
|
||||
name: "Total",
|
||||
title: title("Supply"),
|
||||
bottom: createGroupedSupplyTotalSeries(list, { relativeMetrics: supplyRelativeMetrics }),
|
||||
},
|
||||
{
|
||||
name: "in profit",
|
||||
name: "In Profit",
|
||||
title: title("Supply In Profit"),
|
||||
bottom: createGroupedSupplyInProfitSeries(list, { relativeMetrics: profitRelativeMetrics }),
|
||||
},
|
||||
{
|
||||
name: "in loss",
|
||||
name: "In Loss",
|
||||
title: title("Supply In Loss"),
|
||||
bottom: createGroupedSupplyInLossSeries(list, { relativeMetrics: lossRelativeMetrics }),
|
||||
},
|
||||
@@ -404,18 +404,6 @@ export function createSingleCoinsDestroyedSeries(cohort) {
|
||||
unit: Unit.coindays,
|
||||
defaultActive: false,
|
||||
}),
|
||||
line({
|
||||
metric: tree.activity.satblocksDestroyed,
|
||||
name: "Satblocks",
|
||||
color,
|
||||
unit: Unit.satblocks,
|
||||
}),
|
||||
line({
|
||||
metric: tree.activity.satdaysDestroyed,
|
||||
name: "Satdays",
|
||||
color,
|
||||
unit: Unit.satdays,
|
||||
}),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -451,38 +439,6 @@ export function createGroupedCoindaysDestroyedSeries(list) {
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create satblocks destroyed series for grouped cohorts (comparison)
|
||||
* @param {readonly CohortObject[]} list
|
||||
* @returns {AnyFetchedSeriesBlueprint[]}
|
||||
*/
|
||||
export function createGroupedSatblocksDestroyedSeries(list) {
|
||||
return list.flatMap(({ color, name, tree }) => [
|
||||
line({
|
||||
metric: tree.activity.satblocksDestroyed,
|
||||
name,
|
||||
color,
|
||||
unit: Unit.satblocks,
|
||||
}),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create satdays destroyed series for grouped cohorts (comparison)
|
||||
* @param {readonly CohortObject[]} list
|
||||
* @returns {AnyFetchedSeriesBlueprint[]}
|
||||
*/
|
||||
export function createGroupedSatdaysDestroyedSeries(list) {
|
||||
return list.flatMap(({ color, name, tree }) => [
|
||||
line({
|
||||
metric: tree.activity.satdaysDestroyed,
|
||||
name,
|
||||
color,
|
||||
unit: Unit.satdays,
|
||||
}),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create sent series (sats, btc, usd) for single cohort - all on one chart
|
||||
* @param {CohortObject} cohort
|
||||
|
||||
@@ -136,7 +136,7 @@ export function createCohortFolderWithAdjusted(ctx, args) {
|
||||
createSingleUtxoCountChart(args, title),
|
||||
createSingleRealizedSectionWithAdjusted(ctx, args, title),
|
||||
createSingleUnrealizedSectionWithMarketCap(ctx, args, title),
|
||||
createCostBasisSection({ cohort: args, title }),
|
||||
createCostBasisSection(ctx, { cohort: args, title }),
|
||||
createSingleActivitySectionWithAdjusted(ctx, args, title),
|
||||
],
|
||||
};
|
||||
@@ -249,7 +249,7 @@ export function createCohortFolderBasicWithMarketCap(ctx, args) {
|
||||
createSingleUtxoCountChart(args, title),
|
||||
createSingleRealizedSectionBasic(ctx, args, title),
|
||||
createSingleUnrealizedSectionWithMarketCapOnly(ctx, args, title),
|
||||
createCostBasisSection({ cohort: args, title }),
|
||||
createCostBasisSection(ctx, { cohort: args, title }),
|
||||
createActivitySection({ ctx, cohort: args, title }),
|
||||
],
|
||||
};
|
||||
@@ -285,7 +285,7 @@ export function createCohortFolderBasicWithoutMarketCap(ctx, args) {
|
||||
createSingleUtxoCountChart(args, title),
|
||||
createSingleRealizedSectionBasic(ctx, args, title),
|
||||
createSingleUnrealizedSectionBase(ctx, args, title),
|
||||
createCostBasisSection({ cohort: args, title }),
|
||||
createCostBasisSection(ctx, { cohort: args, title }),
|
||||
createActivitySection({ ctx, cohort: args, title }),
|
||||
],
|
||||
};
|
||||
@@ -324,7 +324,7 @@ export function createCohortFolderAddress(ctx, args) {
|
||||
createSingleAddrCountChart(ctx, args, title),
|
||||
createSingleRealizedSectionBasic(ctx, args, title),
|
||||
createSingleUnrealizedSectionBase(ctx, args, title),
|
||||
createCostBasisSection({ cohort: args, title }),
|
||||
createCostBasisSection(ctx, { cohort: args, title }),
|
||||
createActivitySection({ ctx, cohort: args, title }),
|
||||
],
|
||||
};
|
||||
@@ -342,7 +342,7 @@ export function createCohortFolderAddress(ctx, args) {
|
||||
*/
|
||||
function createSingleSupplyChart(ctx, cohort, title, options = {}) {
|
||||
return {
|
||||
name: "supply",
|
||||
name: "Supply",
|
||||
title: title("Supply"),
|
||||
bottom: createSingleSupplySeries(ctx, cohort, options),
|
||||
};
|
||||
@@ -356,7 +356,7 @@ function createSingleSupplyChart(ctx, cohort, title, options = {}) {
|
||||
*/
|
||||
function createSingleUtxoCountChart(cohort, title) {
|
||||
return {
|
||||
name: "utxo count",
|
||||
name: "UTXO Count",
|
||||
title: title("UTXO Count"),
|
||||
bottom: createUtxoCountSeries([cohort], false),
|
||||
};
|
||||
@@ -370,7 +370,7 @@ function createSingleUtxoCountChart(cohort, title) {
|
||||
*/
|
||||
function createGroupedUtxoCountChart(list, title) {
|
||||
return {
|
||||
name: "utxo count",
|
||||
name: "UTXO Count",
|
||||
title: title("UTXO Count"),
|
||||
bottom: createUtxoCountSeries(list, true),
|
||||
};
|
||||
@@ -385,7 +385,7 @@ function createGroupedUtxoCountChart(list, title) {
|
||||
*/
|
||||
function createSingleAddrCountChart(ctx, cohort, title) {
|
||||
return {
|
||||
name: "address count",
|
||||
name: "Address Count",
|
||||
title: title("Address Count"),
|
||||
bottom: [
|
||||
line({
|
||||
@@ -406,7 +406,7 @@ function createSingleAddrCountChart(ctx, cohort, title) {
|
||||
*/
|
||||
function createGroupedAddrCountChart(list, title) {
|
||||
return {
|
||||
name: "address count",
|
||||
name: "Address Count",
|
||||
title: title("Address Count"),
|
||||
bottom: list.map(({ color, name, addrCount }) =>
|
||||
line({ metric: addrCount, name, color, unit: Unit.count }),
|
||||
@@ -427,7 +427,7 @@ function createSingleRealizedSectionFull(ctx, cohort, title) {
|
||||
tree: [
|
||||
...createSingleRealizedPriceChartsWithRatio(ctx, cohort, title),
|
||||
{
|
||||
name: "capitalization",
|
||||
name: "Capitalization",
|
||||
title: title("Realized Cap"),
|
||||
bottom: createSingleRealizedCapSeries(ctx, cohort, {
|
||||
extra: createRealizedCapRatioSeries(ctx, cohort.tree),
|
||||
@@ -454,7 +454,7 @@ function createSingleRealizedSectionWithAdjusted(ctx, cohort, title) {
|
||||
tree: [
|
||||
...createSingleRealizedPriceChartsBasic(ctx, cohort, title),
|
||||
{
|
||||
name: "capitalization",
|
||||
name: "Capitalization",
|
||||
title: title("Realized Cap"),
|
||||
bottom: createSingleRealizedCapSeries(ctx, cohort),
|
||||
},
|
||||
@@ -489,7 +489,7 @@ function createGroupedRealizedSectionWithAdjusted(ctx, list, title, { ratioMetri
|
||||
bottom: createRealizedPriceRatioSeries(list),
|
||||
},
|
||||
{
|
||||
name: "capitalization",
|
||||
name: "Capitalization",
|
||||
title: title("Realized Cap"),
|
||||
bottom: createGroupedRealizedCapSeries(list),
|
||||
},
|
||||
@@ -512,7 +512,7 @@ function createSingleRealizedSectionWithPercentiles(ctx, cohort, title) {
|
||||
tree: [
|
||||
...createSingleRealizedPriceChartsWithRatio(ctx, cohort, title),
|
||||
{
|
||||
name: "capitalization",
|
||||
name: "Capitalization",
|
||||
title: title("Realized Cap"),
|
||||
bottom: createSingleRealizedCapSeries(ctx, cohort, {
|
||||
extra: createRealizedCapRatioSeries(ctx, cohort.tree),
|
||||
@@ -539,7 +539,7 @@ function createSingleRealizedSectionBasic(ctx, cohort, title) {
|
||||
tree: [
|
||||
...createSingleRealizedPriceChartsBasic(ctx, cohort, title),
|
||||
{
|
||||
name: "capitalization",
|
||||
name: "Capitalization",
|
||||
title: title("Realized Cap"),
|
||||
bottom: createSingleRealizedCapSeries(ctx, cohort),
|
||||
},
|
||||
@@ -574,7 +574,7 @@ function createGroupedRealizedSectionBasic(ctx, list, title, { ratioMetrics } =
|
||||
bottom: createRealizedPriceRatioSeries(list),
|
||||
},
|
||||
{
|
||||
name: "capitalization",
|
||||
name: "Capitalization",
|
||||
title: title("Realized Cap"),
|
||||
bottom: createGroupedRealizedCapSeries(list),
|
||||
},
|
||||
@@ -593,7 +593,7 @@ function createGroupedRealizedSectionBasic(ctx, list, title, { ratioMetrics } =
|
||||
function createSingleRealizedPriceChart(cohort, title) {
|
||||
const { tree, color } = cohort;
|
||||
return {
|
||||
name: "price",
|
||||
name: "Price",
|
||||
title: title("Realized Price"),
|
||||
top: [
|
||||
line({
|
||||
@@ -651,7 +651,7 @@ function createSingleRealizedPriceChartsBasic(ctx, cohort, title) {
|
||||
return [
|
||||
createSingleRealizedPriceChart(cohort, title),
|
||||
{
|
||||
name: "ratio",
|
||||
name: "Ratio",
|
||||
title: title("Realized Price Ratio"),
|
||||
bottom: [
|
||||
baseline({
|
||||
@@ -693,7 +693,7 @@ function createSingleRealizedCapSeries(ctx, cohort, { extra = [] } = {}) {
|
||||
}),
|
||||
baseline({
|
||||
metric: tree.realized.realizedCap30dDelta,
|
||||
name: "30d change",
|
||||
name: "1m Change",
|
||||
unit: Unit.usd,
|
||||
defaultActive: false,
|
||||
}),
|
||||
@@ -789,7 +789,7 @@ function createSingleRealizedPnlSection(ctx, cohort, title, { extra = [] } = {})
|
||||
|
||||
return [
|
||||
{
|
||||
name: "pnl",
|
||||
name: "P&L",
|
||||
title: title("Realized P&L"),
|
||||
bottom: [
|
||||
...fromBlockCountWithUnit(
|
||||
@@ -849,7 +849,7 @@ function createSingleRealizedPnlSection(ctx, cohort, title, { extra = [] } = {})
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Net pnl",
|
||||
name: "Net P&L",
|
||||
title: title("Net Realized P&L"),
|
||||
bottom: [
|
||||
...fromBlockCountWithUnit(
|
||||
@@ -859,7 +859,7 @@ function createSingleRealizedPnlSection(ctx, cohort, title, { extra = [] } = {})
|
||||
),
|
||||
baseline({
|
||||
metric: tree.realized.netRealizedPnlCumulative30dDelta,
|
||||
name: "Cumulative 30d change",
|
||||
name: "Cumulative 1m Change",
|
||||
unit: Unit.usd,
|
||||
defaultActive: false,
|
||||
}),
|
||||
@@ -877,13 +877,13 @@ function createSingleRealizedPnlSection(ctx, cohort, title, { extra = [] } = {})
|
||||
baseline({
|
||||
metric:
|
||||
tree.realized.netRealizedPnlCumulative30dDeltaRelToRealizedCap,
|
||||
name: "Cumulative 30d change",
|
||||
name: "Cumulative 1m Change",
|
||||
unit: Unit.pctRcap,
|
||||
defaultActive: false,
|
||||
}),
|
||||
baseline({
|
||||
metric: tree.realized.netRealizedPnlCumulative30dDeltaRelToMarketCap,
|
||||
name: "Cumulative 30d change",
|
||||
name: "Cumulative 1m Change",
|
||||
unit: Unit.pctMcap,
|
||||
}),
|
||||
priceLine({ ctx, unit: Unit.pctMcap }),
|
||||
@@ -907,7 +907,7 @@ function createSingleRealizedPnlSection(ctx, cohort, title, { extra = [] } = {})
|
||||
function createGroupedRealizedPnlSections(ctx, list, title, { ratioMetrics } = {}) {
|
||||
return [
|
||||
{
|
||||
name: "profit",
|
||||
name: "Profit",
|
||||
title: title("Realized Profit"),
|
||||
bottom: [
|
||||
...list.flatMap(({ color, name, tree }) => [
|
||||
@@ -928,7 +928,7 @@ function createGroupedRealizedPnlSections(ctx, list, title, { ratioMetrics } = {
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "loss",
|
||||
name: "Loss",
|
||||
title: title("Realized Loss"),
|
||||
bottom: [
|
||||
...list.flatMap(({ color, name, tree }) => [
|
||||
@@ -949,7 +949,7 @@ function createGroupedRealizedPnlSections(ctx, list, title, { ratioMetrics } = {
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Total pnl",
|
||||
name: "Total P&L",
|
||||
title: title("Total Realized P&L"),
|
||||
bottom: [
|
||||
...list.flatMap((cohort) => [
|
||||
@@ -964,7 +964,7 @@ function createGroupedRealizedPnlSections(ctx, list, title, { ratioMetrics } = {
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Net pnl",
|
||||
name: "Net P&L",
|
||||
title: title("Net Realized P&L"),
|
||||
bottom: [
|
||||
...list.flatMap(({ color, name, tree }) => [
|
||||
@@ -986,10 +986,10 @@ function createGroupedRealizedPnlSections(ctx, list, title, { ratioMetrics } = {
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "cumulative",
|
||||
name: "Cumulative",
|
||||
tree: [
|
||||
{
|
||||
name: "profit",
|
||||
name: "Profit",
|
||||
title: title("Cumulative Realized Profit"),
|
||||
bottom: list.flatMap(({ color, name, tree }) => [
|
||||
line({
|
||||
@@ -1001,7 +1001,7 @@ function createGroupedRealizedPnlSections(ctx, list, title, { ratioMetrics } = {
|
||||
]),
|
||||
},
|
||||
{
|
||||
name: "loss",
|
||||
name: "Loss",
|
||||
title: title("Cumulative Realized Loss"),
|
||||
bottom: list.flatMap(({ color, name, tree }) => [
|
||||
line({
|
||||
@@ -1013,7 +1013,7 @@ function createGroupedRealizedPnlSections(ctx, list, title, { ratioMetrics } = {
|
||||
]),
|
||||
},
|
||||
{
|
||||
name: "Net pnl",
|
||||
name: "Net P&L",
|
||||
title: title("Cumulative Net Realized P&L"),
|
||||
bottom: [
|
||||
...list.flatMap(({ color, name, tree }) => [
|
||||
@@ -1028,8 +1028,8 @@ function createGroupedRealizedPnlSections(ctx, list, title, { ratioMetrics } = {
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Net pnl 30d change",
|
||||
title: title("Net Realized P&L 30d Change"),
|
||||
name: "Net P&L 1m Change",
|
||||
title: title("Net Realized P&L 1m Change"),
|
||||
bottom: [
|
||||
...list.flatMap(({ color, name, tree }) => [
|
||||
baseline({
|
||||
@@ -1244,7 +1244,7 @@ function createGroupedAdjustedSoprChart(list, title) {
|
||||
*/
|
||||
function createSingleSoprSectionWithAdjusted(ctx, cohort, title) {
|
||||
return {
|
||||
name: "sopr",
|
||||
name: "SOPR",
|
||||
tree: [
|
||||
createSingleBaseSoprChart(ctx, cohort, title),
|
||||
createSingleAdjustedSoprChart(ctx, cohort, title),
|
||||
@@ -1260,7 +1260,7 @@ function createSingleSoprSectionWithAdjusted(ctx, cohort, title) {
|
||||
*/
|
||||
function createGroupedSoprSectionWithAdjusted(list, title) {
|
||||
return {
|
||||
name: "sopr",
|
||||
name: "SOPR",
|
||||
tree: [
|
||||
createGroupedBaseSoprChart(list, title),
|
||||
createGroupedAdjustedSoprChart(list, title),
|
||||
@@ -1277,7 +1277,7 @@ function createGroupedSoprSectionWithAdjusted(list, title) {
|
||||
*/
|
||||
function createSingleSoprSectionBasic(ctx, cohort, title) {
|
||||
return {
|
||||
name: "sopr",
|
||||
name: "SOPR",
|
||||
tree: [createSingleBaseSoprChart(ctx, cohort, title)],
|
||||
};
|
||||
}
|
||||
@@ -1290,7 +1290,7 @@ function createSingleSoprSectionBasic(ctx, cohort, title) {
|
||||
*/
|
||||
function createGroupedSoprSectionBasic(list, title) {
|
||||
return {
|
||||
name: "sopr",
|
||||
name: "SOPR",
|
||||
tree: [createGroupedBaseSoprChart(list, title)],
|
||||
};
|
||||
}
|
||||
@@ -1494,7 +1494,7 @@ function createNetUnrealizedPnlBaseMetric(tree) {
|
||||
*/
|
||||
function createNuplChart(ctx, rel, title) {
|
||||
return {
|
||||
name: "nupl",
|
||||
name: "NUPL",
|
||||
title: title("NUPL"),
|
||||
bottom: [
|
||||
baseline({
|
||||
@@ -1516,7 +1516,7 @@ function createNuplChart(ctx, rel, title) {
|
||||
*/
|
||||
function createGroupedNuplChart(ctx, list, title) {
|
||||
return {
|
||||
name: "nupl",
|
||||
name: "NUPL",
|
||||
title: title("NUPL"),
|
||||
bottom: [
|
||||
...list.map(({ color, name, tree }) =>
|
||||
@@ -1552,7 +1552,7 @@ function createUnrealizedSection({ ctx, tree, title, pnl = [], netPnl = [], char
|
||||
name: "Unrealized",
|
||||
tree: [
|
||||
{
|
||||
name: "pnl",
|
||||
name: "P&L",
|
||||
title: title("Unrealized P&L"),
|
||||
bottom: [
|
||||
...createUnrealizedPnlBaseMetrics(ctx, tree),
|
||||
@@ -1561,7 +1561,7 @@ function createUnrealizedSection({ ctx, tree, title, pnl = [], netPnl = [], char
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Net pnl",
|
||||
name: "Net P&L",
|
||||
title: title("Net Unrealized P&L"),
|
||||
bottom: [
|
||||
createNetUnrealizedPnlBaseMetric(tree),
|
||||
@@ -1590,7 +1590,7 @@ function createGroupedUnrealizedSection({ list, title, netPnlMetrics, charts = [
|
||||
tree: [
|
||||
...createGroupedUnrealizedBaseCharts(list, title),
|
||||
{
|
||||
name: "Net pnl",
|
||||
name: "Net P&L",
|
||||
title: title("Net Unrealized P&L"),
|
||||
bottom: [
|
||||
...list.flatMap((cohort) => [
|
||||
@@ -1725,7 +1725,7 @@ function createSingleUnrealizedSectionBase(ctx, cohort, title) {
|
||||
function createGroupedUnrealizedBaseCharts(list, title) {
|
||||
return [
|
||||
{
|
||||
name: "profit",
|
||||
name: "Profit",
|
||||
title: title("Unrealized Profit"),
|
||||
bottom: list.flatMap(({ color, name, tree }) => [
|
||||
line({
|
||||
@@ -1737,7 +1737,7 @@ function createGroupedUnrealizedBaseCharts(list, title) {
|
||||
]),
|
||||
},
|
||||
{
|
||||
name: "loss",
|
||||
name: "Loss",
|
||||
title: title("Unrealized Loss"),
|
||||
bottom: list.flatMap(({ color, name, tree }) => [
|
||||
line({
|
||||
@@ -1749,7 +1749,7 @@ function createGroupedUnrealizedBaseCharts(list, title) {
|
||||
]),
|
||||
},
|
||||
{
|
||||
name: "total pnl",
|
||||
name: "Total P&L",
|
||||
title: title("Unrealized Total P&L"),
|
||||
bottom: list.flatMap(({ color, name, tree }) => [
|
||||
line({
|
||||
@@ -1918,19 +1918,21 @@ function createGroupedUnrealizedSectionAgeRange(list, title) {
|
||||
|
||||
/**
|
||||
* Generic single cost basis section builder - callers pass optional percentiles
|
||||
* @param {PartialContext} ctx
|
||||
* @param {Object} args
|
||||
* @param {UtxoCohortObject} args.cohort
|
||||
* @param {(metric: string) => string} args.title
|
||||
* @param {PartialChartOption[]} [args.charts] - Extra charts (e.g., percentiles)
|
||||
* @returns {PartialOptionsGroup}
|
||||
*/
|
||||
function createCostBasisSection({ cohort, title, charts = [] }) {
|
||||
function createCostBasisSection(ctx, { cohort, title, charts = [] }) {
|
||||
const { colors } = ctx;
|
||||
const { color, tree } = cohort;
|
||||
return {
|
||||
name: "Cost Basis",
|
||||
tree: [
|
||||
{
|
||||
name: charts.length > 0 ? "Average" : "cost basis",
|
||||
name: "Average",
|
||||
title: title("Cost Basis"),
|
||||
top: [
|
||||
line({
|
||||
@@ -1940,16 +1942,41 @@ function createCostBasisSection({ cohort, title, charts = [] }) {
|
||||
unit: Unit.usd,
|
||||
}),
|
||||
line({
|
||||
metric: tree.costBasis.min,
|
||||
name: "Min",
|
||||
color,
|
||||
metric: tree.costBasis.max,
|
||||
name: "Max",
|
||||
color: colors.green,
|
||||
unit: Unit.usd,
|
||||
defaultActive: false,
|
||||
}),
|
||||
line({
|
||||
metric: tree.costBasis.min,
|
||||
name: "Min",
|
||||
color: colors.red,
|
||||
unit: Unit.usd,
|
||||
defaultActive: false,
|
||||
}),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Max",
|
||||
title: title("Max Cost Basis"),
|
||||
top: [
|
||||
line({
|
||||
metric: tree.costBasis.max,
|
||||
name: "Max",
|
||||
color,
|
||||
color: colors.green,
|
||||
unit: Unit.usd,
|
||||
}),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Min",
|
||||
title: title("Min Cost Basis"),
|
||||
top: [
|
||||
line({
|
||||
metric: tree.costBasis.min,
|
||||
name: "Min",
|
||||
color: colors.red,
|
||||
unit: Unit.usd,
|
||||
}),
|
||||
],
|
||||
@@ -1984,13 +2011,6 @@ function createGroupedCostBasisSection({ list, title, charts = [] }) {
|
||||
}),
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "Min",
|
||||
title: title("Min Cost Basis"),
|
||||
top: list.map(({ color, name, tree }) =>
|
||||
line({ metric: tree.costBasis.min, name, color, unit: Unit.usd }),
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "Max",
|
||||
title: title("Max Cost Basis"),
|
||||
@@ -1998,6 +2018,13 @@ function createGroupedCostBasisSection({ list, title, charts = [] }) {
|
||||
line({ metric: tree.costBasis.max, name, color, unit: Unit.usd }),
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "Min",
|
||||
title: title("Min Cost Basis"),
|
||||
top: list.map(({ color, name, tree }) =>
|
||||
line({ metric: tree.costBasis.min, name, color, unit: Unit.usd }),
|
||||
),
|
||||
},
|
||||
...charts,
|
||||
],
|
||||
};
|
||||
@@ -2016,12 +2043,12 @@ function createGroupedCostBasisSection({ list, title, charts = [] }) {
|
||||
*/
|
||||
function createSingleCostBasisSectionWithPercentiles(ctx, cohort, title) {
|
||||
const { colors } = ctx;
|
||||
return createCostBasisSection({
|
||||
return createCostBasisSection(ctx, {
|
||||
cohort,
|
||||
title,
|
||||
charts: [
|
||||
{
|
||||
name: "percentiles",
|
||||
name: "Percentiles",
|
||||
title: title("Cost Basis Percentiles"),
|
||||
top: createCostBasisPercentilesSeries(colors, [cohort], false),
|
||||
},
|
||||
@@ -2043,7 +2070,7 @@ function createGroupedCostBasisSectionWithPercentiles(ctx, list, title) {
|
||||
title,
|
||||
charts: [
|
||||
{
|
||||
name: "percentiles",
|
||||
name: "Percentiles",
|
||||
title: title("Cost Basis Percentiles"),
|
||||
top: createCostBasisPercentilesSeries(colors, list, true),
|
||||
},
|
||||
@@ -2091,7 +2118,7 @@ function createActivitySection({ ctx, cohort, title, valueMetrics = [] }) {
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "value",
|
||||
name: "Value",
|
||||
title: title("Value Created & Destroyed"),
|
||||
bottom: [
|
||||
line({ metric: tree.realized.valueCreated, name: "Created", color: colors.emerald, unit: Unit.usd }),
|
||||
@@ -2107,8 +2134,6 @@ function createActivitySection({ ctx, cohort, title, valueMetrics = [] }) {
|
||||
line({ metric: tree.activity.coinblocksDestroyed.cumulative, name: "Cumulative", color, unit: Unit.coinblocks, defaultActive: false }),
|
||||
line({ metric: tree.activity.coindaysDestroyed.sum, name: "Coindays", color, unit: Unit.coindays }),
|
||||
line({ metric: tree.activity.coindaysDestroyed.cumulative, name: "Cumulative", color, unit: Unit.coindays, defaultActive: false }),
|
||||
line({ metric: tree.activity.satblocksDestroyed, name: "Satblocks", color, unit: Unit.satblocks }),
|
||||
line({ metric: tree.activity.satdaysDestroyed, name: "Satdays", color, unit: Unit.satdays }),
|
||||
],
|
||||
},
|
||||
],
|
||||
@@ -2136,17 +2161,17 @@ function createGroupedActivitySection({ list, title, valueTree }) {
|
||||
]),
|
||||
},
|
||||
{
|
||||
name: "value",
|
||||
name: "Value",
|
||||
tree: valueTree ?? [
|
||||
{
|
||||
name: "created",
|
||||
name: "Created",
|
||||
title: title("Value Created"),
|
||||
bottom: list.flatMap(({ color, name, tree }) => [
|
||||
line({ metric: tree.realized.valueCreated, name, color, unit: Unit.usd }),
|
||||
]),
|
||||
},
|
||||
{
|
||||
name: "destroyed",
|
||||
name: "Destroyed",
|
||||
title: title("Value Destroyed"),
|
||||
bottom: list.flatMap(({ color, name, tree }) => [
|
||||
line({ metric: tree.realized.valueDestroyed, name, color, unit: Unit.usd }),
|
||||
@@ -2216,7 +2241,7 @@ function createGroupedActivitySectionWithAdjusted(list, title) {
|
||||
title,
|
||||
valueTree: [
|
||||
{
|
||||
name: "created",
|
||||
name: "Created",
|
||||
tree: [
|
||||
{
|
||||
name: "Normal",
|
||||
@@ -2235,7 +2260,7 @@ function createGroupedActivitySectionWithAdjusted(list, title) {
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "destroyed",
|
||||
name: "Destroyed",
|
||||
tree: [
|
||||
{
|
||||
name: "Normal",
|
||||
|
||||
@@ -115,7 +115,8 @@ export function initOptions(brk) {
|
||||
}
|
||||
|
||||
// Remove from set if manual price line already exists
|
||||
if (blueprint.type === "Line") {
|
||||
// Note: line() doesn't set type, so undefined means Line
|
||||
if (blueprint.type === "Line" || blueprint.type === undefined) {
|
||||
const path = Object.values(blueprint.metric.by)[0]?.path ?? "";
|
||||
if (path.includes("constant_")) {
|
||||
priceLines.get(unit)?.delete(parseFloat(blueprint.title));
|
||||
|
||||
@@ -85,7 +85,7 @@ export function createPriceWithRatioOptions(
|
||||
|
||||
return [
|
||||
{
|
||||
name: "price",
|
||||
name: "Price",
|
||||
title,
|
||||
top: [line({ metric: priceMetric, name: legend, color, unit: Unit.usd })],
|
||||
},
|
||||
@@ -100,6 +100,9 @@ export function createPriceWithRatioOptions(
|
||||
];
|
||||
}
|
||||
|
||||
/** Common period IDs to show at top level */
|
||||
const COMMON_PERIODS = ["1w", "1m", "200d", "1y", "200w", "4y"];
|
||||
|
||||
/**
|
||||
* @param {PartialContext} ctx
|
||||
* @param {MarketMovingAverage} movingAverage
|
||||
@@ -113,35 +116,54 @@ export function createAveragesSection(ctx, movingAverage) {
|
||||
* @param {string} label
|
||||
* @param {ReturnType<typeof buildSmaAverages> | ReturnType<typeof buildEmaAverages>} averages
|
||||
*/
|
||||
const createSubSection = (label, averages) => ({
|
||||
name: label,
|
||||
tree: [
|
||||
{
|
||||
name: "Compare",
|
||||
title: `Price ${label}s`,
|
||||
top: averages.map(({ id, color, ratio }) =>
|
||||
line({
|
||||
metric: ratio.price,
|
||||
name: id,
|
||||
const createSubSection = (label, averages) => {
|
||||
const commonAverages = averages.filter(({ id }) => COMMON_PERIODS.includes(id));
|
||||
const moreAverages = averages.filter(({ id }) => !COMMON_PERIODS.includes(id));
|
||||
|
||||
return {
|
||||
name: label,
|
||||
tree: [
|
||||
{
|
||||
name: "Compare",
|
||||
title: `Price ${label}s`,
|
||||
top: averages.map(({ id, color, ratio }) =>
|
||||
line({
|
||||
metric: ratio.price,
|
||||
name: id,
|
||||
color,
|
||||
unit: Unit.usd,
|
||||
}),
|
||||
),
|
||||
},
|
||||
// Common periods at top level
|
||||
...commonAverages.map(({ name, color, ratio }) => ({
|
||||
name,
|
||||
tree: createPriceWithRatioOptions(ctx, {
|
||||
ratio,
|
||||
title: `${name} ${label}`,
|
||||
legend: "average",
|
||||
color,
|
||||
unit: Unit.usd,
|
||||
}),
|
||||
),
|
||||
},
|
||||
...averages.map(({ name, color, ratio }) => ({
|
||||
name,
|
||||
tree: createPriceWithRatioOptions(ctx, {
|
||||
ratio,
|
||||
title: `${name} ${label}`,
|
||||
legend: "average",
|
||||
color,
|
||||
}),
|
||||
})),
|
||||
],
|
||||
});
|
||||
})),
|
||||
// Less common periods in "More..." folder
|
||||
{
|
||||
name: "More...",
|
||||
tree: moreAverages.map(({ name, color, ratio }) => ({
|
||||
name,
|
||||
tree: createPriceWithRatioOptions(ctx, {
|
||||
ratio,
|
||||
title: `${name} ${label}`,
|
||||
legend: "average",
|
||||
color,
|
||||
}),
|
||||
})),
|
||||
},
|
||||
],
|
||||
};
|
||||
};
|
||||
|
||||
return {
|
||||
name: "Averages",
|
||||
name: "Moving Averages",
|
||||
tree: [
|
||||
createSubSection("SMA", smaAverages),
|
||||
createSubSection("EMA", emaAverages),
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
/** Bands indicators (MinMax, Mayer Multiple) */
|
||||
|
||||
import { Unit } from "../../../utils/units.js";
|
||||
import { line } from "../../series.js";
|
||||
import { Unit } from "../../utils/units.js";
|
||||
import { line } from "../series.js";
|
||||
|
||||
/**
|
||||
* Create Bands section
|
||||
@@ -4,9 +4,12 @@ import { localhost } from "../../utils/env.js";
|
||||
import { Unit } from "../../utils/units.js";
|
||||
import { candlestick, line } from "../series.js";
|
||||
import { createAveragesSection } from "./averages.js";
|
||||
import { createPerformanceSection } from "./performance.js";
|
||||
import { createIndicatorsSection } from "./indicators/index.js";
|
||||
import { createInvestingSection } from "./investing.js";
|
||||
import { createReturnsSection } from "./performance.js";
|
||||
import { createMomentumSection } from "./momentum.js";
|
||||
import { createVolatilitySection } from "./volatility.js";
|
||||
import { createBandsSection } from "./bands.js";
|
||||
import { createValuationSection } from "./onchain.js";
|
||||
import { createDcaVsLumpSumSection, createDcaByYearSection } from "./investing.js";
|
||||
|
||||
/**
|
||||
* Create Market section
|
||||
@@ -161,22 +164,29 @@ export function createMarketSection(ctx) {
|
||||
],
|
||||
},
|
||||
|
||||
// Averages
|
||||
// Moving Averages
|
||||
createAveragesSection(ctx, movingAverage),
|
||||
|
||||
// Performance
|
||||
createPerformanceSection(ctx, returns),
|
||||
// Returns
|
||||
createReturnsSection(ctx, returns),
|
||||
|
||||
// Indicators
|
||||
createIndicatorsSection(ctx, {
|
||||
volatility,
|
||||
range,
|
||||
movingAverage,
|
||||
indicators,
|
||||
}),
|
||||
// Volatility
|
||||
createVolatilitySection(ctx, { volatility, range }),
|
||||
|
||||
// Investing
|
||||
createInvestingSection(ctx, { dca, lookback, returns }),
|
||||
// Momentum
|
||||
createMomentumSection(ctx, indicators),
|
||||
|
||||
// Bands
|
||||
createBandsSection(ctx, { range, movingAverage }),
|
||||
|
||||
// Valuation
|
||||
createValuationSection(ctx, { indicators, movingAverage }),
|
||||
|
||||
// DCA vs Lump Sum
|
||||
createDcaVsLumpSumSection(ctx, { dca, lookback, returns }),
|
||||
|
||||
// DCA by Year
|
||||
createDcaByYearSection(ctx, { dca }),
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
/** Indicators section - Main entry point */
|
||||
|
||||
import { createMomentumSection } from "./momentum.js";
|
||||
import { createVolatilitySection } from "./volatility.js";
|
||||
import { createBandsSection } from "./bands.js";
|
||||
import { createOnchainSection } from "./onchain.js";
|
||||
|
||||
/**
|
||||
* Create Indicators section
|
||||
* @param {PartialContext} ctx
|
||||
* @param {Object} args
|
||||
* @param {Market["volatility"]} args.volatility
|
||||
* @param {Market["range"]} args.range
|
||||
* @param {Market["movingAverage"]} args.movingAverage
|
||||
* @param {Market["indicators"]} args.indicators
|
||||
*/
|
||||
export function createIndicatorsSection(ctx, { volatility, range, movingAverage, indicators }) {
|
||||
return {
|
||||
name: "Indicators",
|
||||
tree: [
|
||||
createMomentumSection(ctx, indicators),
|
||||
createVolatilitySection(ctx, { volatility, range }),
|
||||
createBandsSection(ctx, { range, movingAverage }),
|
||||
createOnchainSection(ctx, { indicators, movingAverage }),
|
||||
],
|
||||
};
|
||||
}
|
||||
@@ -32,20 +32,115 @@ export function buildDcaClasses(colors, dca) {
|
||||
costBasis: dca.classAveragePrice[`_${year}`],
|
||||
returns: dca.classReturns[`_${year}`],
|
||||
stack: dca.classStack[`_${year}`],
|
||||
daysInProfit: dca.classDaysInProfit[`_${year}`],
|
||||
daysInLoss: dca.classDaysInLoss[`_${year}`],
|
||||
maxDrawdown: dca.classMaxDrawdown[`_${year}`],
|
||||
maxReturn: dca.classMaxReturn[`_${year}`],
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Investing section
|
||||
* Create DCA vs Lump Sum section
|
||||
* @param {PartialContext} ctx
|
||||
* @param {Object} args
|
||||
* @param {Market["dca"]} args.dca
|
||||
* @param {Market["lookback"]} args.lookback
|
||||
* @param {Market["returns"]} args.returns
|
||||
*/
|
||||
export function createInvestingSection(ctx, { dca, lookback, returns }) {
|
||||
export function createDcaVsLumpSumSection(ctx, { dca, lookback, returns }) {
|
||||
const { colors } = ctx;
|
||||
const dcaClasses = buildDcaClasses(colors, dca);
|
||||
|
||||
/**
|
||||
* @param {string} name
|
||||
* @param {ShortPeriodKey | LongPeriodKey} key
|
||||
*/
|
||||
const costBasisChart = (name, key) => ({
|
||||
name: "Cost Basis",
|
||||
title: `${name} Cost Basis`,
|
||||
top: [
|
||||
line({
|
||||
metric: dca.periodAveragePrice[key],
|
||||
name: "DCA",
|
||||
color: colors.green,
|
||||
unit: Unit.usd,
|
||||
}),
|
||||
line({
|
||||
metric: lookback[key],
|
||||
name: "Lump sum",
|
||||
color: colors.orange,
|
||||
unit: Unit.usd,
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
/** @param {string} name @param {ShortPeriodKey | LongPeriodKey} key */
|
||||
const daysInProfitChart = (name, key) => ({
|
||||
name: "Days in Profit",
|
||||
title: `${name} Days in Profit`,
|
||||
top: [
|
||||
line({ metric: dca.periodAveragePrice[key], name: "DCA", color: colors.green, unit: Unit.usd }),
|
||||
line({ metric: lookback[key], name: "Lump sum", color: colors.orange, unit: Unit.usd }),
|
||||
],
|
||||
bottom: [
|
||||
line({ metric: dca.periodDaysInProfit[key], name: "DCA", color: colors.green, unit: Unit.days }),
|
||||
line({ metric: dca.periodLumpSumDaysInProfit[key], name: "Lump sum", color: colors.orange, unit: Unit.days }),
|
||||
],
|
||||
});
|
||||
|
||||
/** @param {string} name @param {ShortPeriodKey | LongPeriodKey} key */
|
||||
const daysInLossChart = (name, key) => ({
|
||||
name: "Days in Loss",
|
||||
title: `${name} Days in Loss`,
|
||||
top: [
|
||||
line({ metric: dca.periodAveragePrice[key], name: "DCA", color: colors.green, unit: Unit.usd }),
|
||||
line({ metric: lookback[key], name: "Lump sum", color: colors.orange, unit: Unit.usd }),
|
||||
],
|
||||
bottom: [
|
||||
line({ metric: dca.periodDaysInLoss[key], name: "DCA", color: colors.red, unit: Unit.days }),
|
||||
line({ metric: dca.periodLumpSumDaysInLoss[key], name: "Lump sum", color: colors.orange, unit: Unit.days }),
|
||||
],
|
||||
});
|
||||
|
||||
/** @param {string} name @param {ShortPeriodKey | LongPeriodKey} key */
|
||||
const maxDrawdownChart = (name, key) => ({
|
||||
name: "Max Drawdown",
|
||||
title: `${name} Max Drawdown`,
|
||||
top: [
|
||||
line({ metric: dca.periodAveragePrice[key], name: "DCA", color: colors.green, unit: Unit.usd }),
|
||||
line({ metric: lookback[key], name: "Lump sum", color: colors.orange, unit: Unit.usd }),
|
||||
],
|
||||
bottom: [
|
||||
line({ metric: dca.periodMaxDrawdown[key], name: "DCA", color: colors.green, unit: Unit.percentage }),
|
||||
line({ metric: dca.periodLumpSumMaxDrawdown[key], name: "Lump sum", color: colors.orange, unit: Unit.percentage }),
|
||||
],
|
||||
});
|
||||
|
||||
/** @param {string} name @param {ShortPeriodKey | LongPeriodKey} key */
|
||||
const maxReturnChart = (name, key) => ({
|
||||
name: "Max Return",
|
||||
title: `${name} Max Return`,
|
||||
top: [
|
||||
line({ metric: dca.periodAveragePrice[key], name: "DCA", color: colors.green, unit: Unit.usd }),
|
||||
line({ metric: lookback[key], name: "Lump sum", color: colors.orange, unit: Unit.usd }),
|
||||
],
|
||||
bottom: [
|
||||
line({ metric: dca.periodMaxReturn[key], name: "DCA", color: colors.green, unit: Unit.percentage }),
|
||||
line({ metric: dca.periodLumpSumMaxReturn[key], name: "Lump sum", color: colors.orange, unit: Unit.percentage }),
|
||||
],
|
||||
});
|
||||
|
||||
/**
|
||||
* @param {string} name
|
||||
* @param {ShortPeriodKey | LongPeriodKey} key
|
||||
*/
|
||||
const stackChart = (name, key) => ({
|
||||
name: "Stack",
|
||||
title: `${name} Stack`,
|
||||
bottom: [
|
||||
...satsBtcUsd(dca.periodStack[key], "DCA", colors.green),
|
||||
...satsBtcUsd(dca.periodLumpSumStack[key], "Lump sum", colors.orange),
|
||||
],
|
||||
});
|
||||
|
||||
/**
|
||||
* @param {string} id
|
||||
@@ -56,31 +151,34 @@ export function createInvestingSection(ctx, { dca, lookback, returns }) {
|
||||
return {
|
||||
name,
|
||||
tree: [
|
||||
{
|
||||
name: "Cost basis",
|
||||
title: `${name} Cost Basis`,
|
||||
top: [
|
||||
line({ metric: dca.periodAveragePrice[key], name: "DCA", color: colors.green, unit: Unit.usd }),
|
||||
line({ metric: lookback[key], name: "Lump sum", color: colors.orange, unit: Unit.usd }),
|
||||
],
|
||||
},
|
||||
costBasisChart(name, key),
|
||||
{
|
||||
name: "Returns",
|
||||
title: `${name} Returns`,
|
||||
bottom: [
|
||||
baseline({ metric: dca.periodReturns[key], name: "DCA", unit: Unit.percentage }),
|
||||
baseline({ metric: returns.priceReturns[key], name: "Lump sum", color: [colors.cyan, colors.orange], unit: Unit.percentage }),
|
||||
priceLine({ ctx, unit: Unit.percentage }),
|
||||
baseline({
|
||||
metric: dca.periodReturns[key],
|
||||
name: "DCA",
|
||||
unit: Unit.percentage,
|
||||
}),
|
||||
baseline({
|
||||
metric: dca.periodLumpSumReturns[key],
|
||||
name: "Lump sum",
|
||||
color: [colors.cyan, colors.orange],
|
||||
unit: Unit.percentage,
|
||||
}),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Stack",
|
||||
title: `${name} Stack`,
|
||||
bottom: [
|
||||
...satsBtcUsd(dca.periodStack[key], "DCA", colors.green),
|
||||
...satsBtcUsd(dca.periodLumpSumStack[key], "Lump sum", colors.orange),
|
||||
name: "Profitability",
|
||||
tree: [
|
||||
daysInProfitChart(name, key),
|
||||
daysInLossChart(name, key),
|
||||
maxDrawdownChart(name, key),
|
||||
maxReturnChart(name, key),
|
||||
],
|
||||
},
|
||||
stackChart(name, key),
|
||||
],
|
||||
};
|
||||
};
|
||||
@@ -94,142 +192,226 @@ export function createInvestingSection(ctx, { dca, lookback, returns }) {
|
||||
return {
|
||||
name,
|
||||
tree: [
|
||||
{
|
||||
name: "Cost basis",
|
||||
title: `${name} Cost Basis`,
|
||||
top: [
|
||||
line({ metric: dca.periodAveragePrice[key], name: "DCA", color: colors.green, unit: Unit.usd }),
|
||||
line({ metric: lookback[key], name: "Lump sum", color: colors.orange, unit: Unit.usd }),
|
||||
],
|
||||
},
|
||||
costBasisChart(name, key),
|
||||
{
|
||||
name: "Returns",
|
||||
title: `${name} Returns`,
|
||||
bottom: [
|
||||
baseline({ metric: dca.periodReturns[key], name: "DCA", unit: Unit.percentage }),
|
||||
baseline({ metric: returns.priceReturns[key], name: "Lump sum", color: [colors.cyan, colors.orange], unit: Unit.percentage }),
|
||||
line({ metric: dca.periodCagr[key], name: "DCA CAGR", color: colors.purple, unit: Unit.percentage, defaultActive: false }),
|
||||
line({ metric: returns.cagr[key], name: "Lump sum CAGR", color: colors.indigo, unit: Unit.percentage, defaultActive: false }),
|
||||
baseline({
|
||||
metric: dca.periodReturns[key],
|
||||
name: "DCA",
|
||||
unit: Unit.percentage,
|
||||
}),
|
||||
baseline({
|
||||
metric: dca.periodLumpSumReturns[key],
|
||||
name: "Lump sum",
|
||||
color: [colors.cyan, colors.orange],
|
||||
unit: Unit.percentage,
|
||||
}),
|
||||
line({
|
||||
metric: dca.periodCagr[key],
|
||||
name: "DCA CAGR",
|
||||
color: colors.purple,
|
||||
unit: Unit.percentage,
|
||||
defaultActive: false,
|
||||
}),
|
||||
line({
|
||||
metric: returns.cagr[key],
|
||||
name: "Lump sum CAGR",
|
||||
color: colors.indigo,
|
||||
unit: Unit.percentage,
|
||||
defaultActive: false,
|
||||
}),
|
||||
priceLine({ ctx, unit: Unit.percentage }),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Stack",
|
||||
title: `${name} Stack`,
|
||||
bottom: [
|
||||
...satsBtcUsd(dca.periodStack[key], "DCA", colors.green),
|
||||
...satsBtcUsd(dca.periodLumpSumStack[key], "Lump sum", colors.orange),
|
||||
name: "Profitability",
|
||||
tree: [
|
||||
daysInProfitChart(name, key),
|
||||
daysInLossChart(name, key),
|
||||
maxDrawdownChart(name, key),
|
||||
maxReturnChart(name, key),
|
||||
],
|
||||
},
|
||||
stackChart(name, key),
|
||||
],
|
||||
};
|
||||
};
|
||||
|
||||
return {
|
||||
name: "Investing",
|
||||
name: "DCA vs Lump Sum",
|
||||
tree: [
|
||||
// DCA vs Lump sum
|
||||
{
|
||||
name: "DCA vs Lump sum",
|
||||
tree: [
|
||||
createPeriodTree("1w", "_1w"),
|
||||
createPeriodTree("1m", "_1m"),
|
||||
createPeriodTree("3m", "_3m"),
|
||||
createPeriodTree("6m", "_6m"),
|
||||
createPeriodTree("1y", "_1y"),
|
||||
createPeriodTreeWithCagr("2y", "_2y"),
|
||||
createPeriodTreeWithCagr("3y", "_3y"),
|
||||
createPeriodTreeWithCagr("4y", "_4y"),
|
||||
createPeriodTreeWithCagr("5y", "_5y"),
|
||||
createPeriodTreeWithCagr("6y", "_6y"),
|
||||
createPeriodTreeWithCagr("8y", "_8y"),
|
||||
createPeriodTreeWithCagr("10y", "_10y"),
|
||||
],
|
||||
},
|
||||
|
||||
// DCA classes
|
||||
{
|
||||
name: "DCA classes",
|
||||
tree: [
|
||||
// Comparison charts (all years overlaid)
|
||||
{
|
||||
name: "Compare",
|
||||
tree: [
|
||||
{
|
||||
name: "Cost basis",
|
||||
title: "DCA Cost Basis",
|
||||
top: dcaClasses.map(
|
||||
({ year, color, defaultActive, costBasis }) =>
|
||||
line({
|
||||
metric: costBasis,
|
||||
name: `${year}`,
|
||||
color,
|
||||
defaultActive,
|
||||
unit: Unit.usd,
|
||||
}),
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "Returns",
|
||||
title: "DCA Returns",
|
||||
bottom: dcaClasses.map(
|
||||
({ year, color, defaultActive, returns }) =>
|
||||
baseline({
|
||||
metric: returns,
|
||||
name: `${year}`,
|
||||
color,
|
||||
defaultActive,
|
||||
unit: Unit.percentage,
|
||||
}),
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "Stack",
|
||||
title: "DCA Stack",
|
||||
bottom: dcaClasses.flatMap(
|
||||
({ year, color, defaultActive, stack }) =>
|
||||
satsBtcUsd(stack, `${year}`, color, { defaultActive }),
|
||||
),
|
||||
},
|
||||
],
|
||||
},
|
||||
// Individual year charts
|
||||
...dcaClasses.map(({ year, color, costBasis, returns, stack }) => ({
|
||||
name: `${year}`,
|
||||
tree: [
|
||||
{
|
||||
name: "Cost basis",
|
||||
title: `${year} Cost Basis`,
|
||||
top: [
|
||||
line({
|
||||
metric: costBasis,
|
||||
name: "Cost basis",
|
||||
color,
|
||||
unit: Unit.usd,
|
||||
}),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Returns",
|
||||
title: `${year} Returns`,
|
||||
bottom: [
|
||||
baseline({
|
||||
metric: returns,
|
||||
name: "Returns",
|
||||
color,
|
||||
unit: Unit.percentage,
|
||||
}),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Stack",
|
||||
title: `${year} Stack`,
|
||||
bottom: satsBtcUsd(stack, "Stack", color),
|
||||
},
|
||||
],
|
||||
})),
|
||||
],
|
||||
},
|
||||
createPeriodTree("1w", "_1w"),
|
||||
createPeriodTree("1m", "_1m"),
|
||||
createPeriodTree("3m", "_3m"),
|
||||
createPeriodTree("6m", "_6m"),
|
||||
createPeriodTree("1y", "_1y"),
|
||||
createPeriodTreeWithCagr("2y", "_2y"),
|
||||
createPeriodTreeWithCagr("3y", "_3y"),
|
||||
createPeriodTreeWithCagr("4y", "_4y"),
|
||||
createPeriodTreeWithCagr("5y", "_5y"),
|
||||
createPeriodTreeWithCagr("6y", "_6y"),
|
||||
createPeriodTreeWithCagr("8y", "_8y"),
|
||||
createPeriodTreeWithCagr("10y", "_10y"),
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create DCA by Year section
|
||||
* @param {PartialContext} ctx
|
||||
* @param {Object} args
|
||||
* @param {Market["dca"]} args.dca
|
||||
*/
|
||||
export function createDcaByYearSection(ctx, { dca }) {
|
||||
const { colors } = ctx;
|
||||
const dcaClasses = buildDcaClasses(colors, dca);
|
||||
|
||||
return {
|
||||
name: "DCA by Year",
|
||||
tree: [
|
||||
// Comparison charts (all years overlaid)
|
||||
{
|
||||
name: "Compare",
|
||||
tree: [
|
||||
{
|
||||
name: "Cost basis",
|
||||
title: "DCA Cost Basis",
|
||||
top: dcaClasses.map(({ year, color, defaultActive, costBasis }) =>
|
||||
line({
|
||||
metric: costBasis,
|
||||
name: `${year}`,
|
||||
color,
|
||||
defaultActive,
|
||||
unit: Unit.usd,
|
||||
}),
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "Returns",
|
||||
title: "DCA Returns",
|
||||
bottom: dcaClasses.map(({ year, defaultActive, returns }) =>
|
||||
baseline({
|
||||
metric: returns,
|
||||
name: `${year}`,
|
||||
defaultActive,
|
||||
unit: Unit.percentage,
|
||||
}),
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "Profitability",
|
||||
title: "DCA Profitability",
|
||||
bottom: [
|
||||
...dcaClasses.map(({ year, color, defaultActive, daysInProfit }) =>
|
||||
line({
|
||||
metric: daysInProfit,
|
||||
name: `${year} Days in Profit`,
|
||||
color,
|
||||
defaultActive,
|
||||
unit: Unit.days,
|
||||
}),
|
||||
),
|
||||
...dcaClasses.map(({ year, color, daysInLoss }) =>
|
||||
line({
|
||||
metric: daysInLoss,
|
||||
name: `${year} Days in Loss`,
|
||||
color,
|
||||
defaultActive: false,
|
||||
unit: Unit.days,
|
||||
}),
|
||||
),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Stack",
|
||||
title: "DCA Stack",
|
||||
bottom: dcaClasses.flatMap(
|
||||
({ year, color, defaultActive, stack }) =>
|
||||
satsBtcUsd(stack, `${year}`, color, { defaultActive }),
|
||||
),
|
||||
},
|
||||
],
|
||||
},
|
||||
// Individual year charts
|
||||
...dcaClasses.map(
|
||||
({
|
||||
year,
|
||||
color,
|
||||
costBasis,
|
||||
returns,
|
||||
stack,
|
||||
daysInProfit,
|
||||
daysInLoss,
|
||||
maxDrawdown,
|
||||
maxReturn,
|
||||
}) => ({
|
||||
name: `${year}`,
|
||||
tree: [
|
||||
{
|
||||
name: "Cost Basis",
|
||||
title: `${year} Cost Basis`,
|
||||
top: [
|
||||
line({
|
||||
metric: costBasis,
|
||||
name: "Cost Basis",
|
||||
color,
|
||||
unit: Unit.usd,
|
||||
}),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Returns",
|
||||
title: `${year} Returns`,
|
||||
bottom: [
|
||||
baseline({
|
||||
metric: returns,
|
||||
name: "Returns",
|
||||
unit: Unit.percentage,
|
||||
}),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Profitability",
|
||||
title: `${year} Profitability`,
|
||||
bottom: [
|
||||
line({
|
||||
metric: daysInProfit,
|
||||
name: "Days in Profit",
|
||||
color: colors.green,
|
||||
unit: Unit.days,
|
||||
}),
|
||||
line({
|
||||
metric: daysInLoss,
|
||||
name: "Days in Loss",
|
||||
color: colors.red,
|
||||
unit: Unit.days,
|
||||
}),
|
||||
line({
|
||||
metric: maxDrawdown,
|
||||
name: "Max Drawdown",
|
||||
color: colors.purple,
|
||||
unit: Unit.percentage,
|
||||
defaultActive: false,
|
||||
}),
|
||||
line({
|
||||
metric: maxReturn,
|
||||
name: "Max Return",
|
||||
color: colors.cyan,
|
||||
unit: Unit.percentage,
|
||||
defaultActive: false,
|
||||
}),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Stack",
|
||||
title: `${year} Stack`,
|
||||
bottom: satsBtcUsd(stack, "Stack", color),
|
||||
},
|
||||
],
|
||||
}),
|
||||
),
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
+3
-3
@@ -1,8 +1,8 @@
|
||||
/** Momentum indicators (RSI, StochRSI, Stochastic, MACD) */
|
||||
|
||||
import { Unit } from "../../../utils/units.js";
|
||||
import { priceLine, priceLines } from "../../constants.js";
|
||||
import { line, histogram } from "../../series.js";
|
||||
import { Unit } from "../../utils/units.js";
|
||||
import { priceLine, priceLines } from "../constants.js";
|
||||
import { line, histogram } from "../series.js";
|
||||
|
||||
/**
|
||||
* Create Momentum section
|
||||
+5
-5
@@ -1,20 +1,20 @@
|
||||
/** On-chain indicators (Pi Cycle, Puell, NVT, Gini) */
|
||||
|
||||
import { Unit } from "../../../utils/units.js";
|
||||
import { baseline, line } from "../../series.js";
|
||||
import { Unit } from "../../utils/units.js";
|
||||
import { baseline, line } from "../series.js";
|
||||
|
||||
/**
|
||||
* Create On-chain section
|
||||
* Create Valuation section
|
||||
* @param {PartialContext} ctx
|
||||
* @param {Object} args
|
||||
* @param {Market["indicators"]} args.indicators
|
||||
* @param {Market["movingAverage"]} args.movingAverage
|
||||
*/
|
||||
export function createOnchainSection(ctx, { indicators, movingAverage }) {
|
||||
export function createValuationSection(ctx, { indicators, movingAverage }) {
|
||||
const { colors } = ctx;
|
||||
|
||||
return {
|
||||
name: "On-chain",
|
||||
name: "Valuation",
|
||||
tree: [
|
||||
{
|
||||
name: "Pi Cycle",
|
||||
@@ -6,55 +6,100 @@ import { baseline } from "../series.js";
|
||||
import { periodIdToName } from "./utils.js";
|
||||
|
||||
/**
|
||||
* Create Performance section
|
||||
* Create Returns section
|
||||
* @param {PartialContext} ctx
|
||||
* @param {Market["returns"]} returns
|
||||
*/
|
||||
export function createPerformanceSection(ctx, returns) {
|
||||
export function createReturnsSection(ctx, returns) {
|
||||
const { colors } = ctx;
|
||||
|
||||
const shortTermPeriods = /** @type {const} */ ([
|
||||
["1d", "_1d", undefined],
|
||||
["1w", "_1w", undefined],
|
||||
["1m", "_1m", undefined],
|
||||
]);
|
||||
|
||||
const mediumTermPeriods = /** @type {const} */ ([
|
||||
["3m", "_3m", undefined],
|
||||
["6m", "_6m", undefined],
|
||||
["1y", "_1y", undefined],
|
||||
]);
|
||||
|
||||
const longTermPeriods = /** @type {const} */ ([
|
||||
["2y", "_2y", "_2y"],
|
||||
["3y", "_3y", "_3y"],
|
||||
["4y", "_4y", "_4y"],
|
||||
["5y", "_5y", "_5y"],
|
||||
["6y", "_6y", "_6y"],
|
||||
["8y", "_8y", "_8y"],
|
||||
["10y", "_10y", "_10y"],
|
||||
]);
|
||||
|
||||
/**
|
||||
* @template {keyof typeof returns.priceReturns} K
|
||||
* @param {readonly [string, K, K | undefined]} period
|
||||
*/
|
||||
const createPeriodChart = ([id, returnKey, cagrKey]) => {
|
||||
const priceReturns = returns.priceReturns[/** @type {K} */ (returnKey)];
|
||||
const cagr = cagrKey ? returns.cagr[/** @type {keyof typeof returns.cagr} */ (cagrKey)] : undefined;
|
||||
const name = periodIdToName(id, true);
|
||||
return {
|
||||
name,
|
||||
title: `${name} Returns`,
|
||||
bottom: [
|
||||
baseline({
|
||||
metric: priceReturns,
|
||||
name: "Total",
|
||||
unit: Unit.percentage,
|
||||
}),
|
||||
...(cagr
|
||||
? [
|
||||
baseline({
|
||||
metric: cagr,
|
||||
name: "CAGR",
|
||||
color: [colors.cyan, colors.orange],
|
||||
unit: Unit.percentage,
|
||||
}),
|
||||
]
|
||||
: []),
|
||||
priceLine({ ctx, unit: Unit.percentage }),
|
||||
],
|
||||
};
|
||||
};
|
||||
|
||||
return {
|
||||
name: "Performance",
|
||||
tree: /** @type {const} */ ([
|
||||
["1d", "_1d", undefined],
|
||||
["1w", "_1w", undefined],
|
||||
["1m", "_1m", undefined],
|
||||
["3m", "_3m", undefined],
|
||||
["6m", "_6m", undefined],
|
||||
["1y", "_1y", undefined],
|
||||
["2y", "_2y", "_2y"],
|
||||
["3y", "_3y", "_3y"],
|
||||
["4y", "_4y", "_4y"],
|
||||
["5y", "_5y", "_5y"],
|
||||
["6y", "_6y", "_6y"],
|
||||
["8y", "_8y", "_8y"],
|
||||
["10y", "_10y", "_10y"],
|
||||
]).map(([id, returnKey, cagrKey]) => {
|
||||
const priceReturns = returns.priceReturns[returnKey];
|
||||
const cagr = cagrKey ? returns.cagr[cagrKey] : undefined;
|
||||
const name = periodIdToName(id, true);
|
||||
return {
|
||||
name,
|
||||
title: `${name} Returns`,
|
||||
name: "Returns",
|
||||
tree: [
|
||||
// Compare all periods
|
||||
{
|
||||
name: "Compare",
|
||||
title: "Returns Comparison",
|
||||
bottom: [
|
||||
baseline({
|
||||
metric: priceReturns,
|
||||
name: "Total",
|
||||
unit: Unit.percentage,
|
||||
}),
|
||||
...(cagr
|
||||
? [
|
||||
baseline({
|
||||
metric: cagr,
|
||||
name: "CAGR",
|
||||
color: [colors.cyan, colors.orange],
|
||||
unit: Unit.percentage,
|
||||
}),
|
||||
]
|
||||
: []),
|
||||
baseline({ metric: returns.priceReturns._1d, name: "1d", color: colors.red, unit: Unit.percentage }),
|
||||
baseline({ metric: returns.priceReturns._1w, name: "1w", color: colors.orange, unit: Unit.percentage }),
|
||||
baseline({ metric: returns.priceReturns._1m, name: "1m", color: colors.yellow, unit: Unit.percentage }),
|
||||
baseline({ metric: returns.priceReturns._3m, name: "3m", color: colors.lime, unit: Unit.percentage, defaultActive: false }),
|
||||
baseline({ metric: returns.priceReturns._6m, name: "6m", color: colors.green, unit: Unit.percentage, defaultActive: false }),
|
||||
baseline({ metric: returns.priceReturns._1y, name: "1y", color: colors.teal, unit: Unit.percentage }),
|
||||
baseline({ metric: returns.priceReturns._4y, name: "4y", color: colors.blue, unit: Unit.percentage }),
|
||||
priceLine({ ctx, unit: Unit.percentage }),
|
||||
],
|
||||
};
|
||||
}),
|
||||
},
|
||||
// Short-term (1d, 1w, 1m)
|
||||
{
|
||||
name: "Short-term",
|
||||
tree: shortTermPeriods.map(createPeriodChart),
|
||||
},
|
||||
// Medium-term (3m, 6m, 1y)
|
||||
{
|
||||
name: "Medium-term",
|
||||
tree: mediumTermPeriods.map(createPeriodChart),
|
||||
},
|
||||
// Long-term (2y+)
|
||||
{
|
||||
name: "Long-term",
|
||||
tree: longTermPeriods.map(createPeriodChart),
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
+3
-3
@@ -1,8 +1,8 @@
|
||||
/** Volatility indicators (Index, True Range, Choppiness, Sharpe, Sortino) */
|
||||
|
||||
import { Unit } from "../../../utils/units.js";
|
||||
import { priceLine, priceLines } from "../../constants.js";
|
||||
import { line } from "../../series.js";
|
||||
import { Unit } from "../../utils/units.js";
|
||||
import { priceLine, priceLines } from "../constants.js";
|
||||
import { line } from "../series.js";
|
||||
|
||||
/**
|
||||
* Create Volatility section
|
||||
@@ -95,62 +95,45 @@ export function createPartialOptions({ brk }) {
|
||||
{
|
||||
name: "Distribution",
|
||||
tree: [
|
||||
// All UTXOs - CohortAll (adjustedSopr + percentiles but no RelToMarketCap)
|
||||
createCohortFolderAll(ctx, cohortAll),
|
||||
// Overview - All UTXOs (adjustedSopr + percentiles but no RelToMarketCap)
|
||||
createCohortFolderAll(ctx, { ...cohortAll, name: "Overview" }),
|
||||
|
||||
// Terms (STH/LTH) - Short is Full, Long has nupl
|
||||
{
|
||||
name: "Terms",
|
||||
tree: [
|
||||
// Compare folder - both have nupl + percentiles
|
||||
createCohortFolderWithNupl(ctx, {
|
||||
name: "Compare",
|
||||
title: "Term",
|
||||
list: [termShort, termLong],
|
||||
}),
|
||||
// Individual cohorts with their specific capabilities
|
||||
createCohortFolderFull(ctx, termShort),
|
||||
createCohortFolderWithNupl(ctx, termLong),
|
||||
],
|
||||
},
|
||||
// STH - Short term holder cohort (Full capability)
|
||||
createCohortFolderFull(ctx, termShort),
|
||||
|
||||
// Types - addressable types have addrCount, others don't
|
||||
{
|
||||
name: "Types",
|
||||
tree: [
|
||||
createCohortFolderAddress(ctx, {
|
||||
name: "Compare",
|
||||
title: "Type",
|
||||
list: typeAddressable,
|
||||
}),
|
||||
...typeAddressable.map(mapAddress),
|
||||
...typeOther.map(mapBasicWithoutMarketCap),
|
||||
],
|
||||
},
|
||||
// LTH - Long term holder cohort (nupl)
|
||||
createCohortFolderWithNupl(ctx, termLong),
|
||||
|
||||
// Age cohorts
|
||||
// STH vs LTH - Direct comparison
|
||||
createCohortFolderWithNupl(ctx, {
|
||||
name: "STH vs LTH",
|
||||
title: "Term",
|
||||
list: [termShort, termLong],
|
||||
}),
|
||||
|
||||
// Ages cohorts
|
||||
{
|
||||
name: "Age",
|
||||
name: "Ages",
|
||||
tree: [
|
||||
// Up To (< X old)
|
||||
// Younger Than (< X old)
|
||||
{
|
||||
name: "Up To",
|
||||
name: "Younger Than",
|
||||
tree: [
|
||||
createCohortFolderWithAdjusted(ctx, {
|
||||
name: "Compare",
|
||||
title: "Age Up To",
|
||||
title: "Age Younger Than",
|
||||
list: upToDate,
|
||||
}),
|
||||
...upToDate.map(mapWithAdjusted),
|
||||
],
|
||||
},
|
||||
// At Least (≥ X old)
|
||||
// Older Than (≥ X old)
|
||||
{
|
||||
name: "At Least",
|
||||
name: "Older Than",
|
||||
tree: [
|
||||
createCohortFolderBasicWithMarketCap(ctx, {
|
||||
name: "Compare",
|
||||
title: "Age At Least",
|
||||
title: "Age Older Than",
|
||||
list: fromDate,
|
||||
}),
|
||||
...fromDate.map(mapBasicWithMarketCap),
|
||||
@@ -171,29 +154,29 @@ export function createPartialOptions({ brk }) {
|
||||
],
|
||||
},
|
||||
|
||||
// Amount cohorts (UTXO size)
|
||||
// Sizes cohorts (UTXO size)
|
||||
{
|
||||
name: "Amount",
|
||||
name: "Sizes",
|
||||
tree: [
|
||||
// Under (< X sats)
|
||||
// Less Than (< X sats)
|
||||
{
|
||||
name: "Under",
|
||||
name: "Less Than",
|
||||
tree: [
|
||||
createCohortFolderBasicWithMarketCap(ctx, {
|
||||
name: "Compare",
|
||||
title: "Amount Under",
|
||||
title: "Size Less Than",
|
||||
list: utxosUnderAmount,
|
||||
}),
|
||||
...utxosUnderAmount.map(mapBasicWithMarketCap),
|
||||
],
|
||||
},
|
||||
// Above (≥ X sats)
|
||||
// More Than (≥ X sats)
|
||||
{
|
||||
name: "Above",
|
||||
name: "More Than",
|
||||
tree: [
|
||||
createCohortFolderBasicWithMarketCap(ctx, {
|
||||
name: "Compare",
|
||||
title: "Amount Above",
|
||||
title: "Size More Than",
|
||||
list: utxosAboveAmount,
|
||||
}),
|
||||
...utxosAboveAmount.map(mapBasicWithMarketCap),
|
||||
@@ -205,7 +188,7 @@ export function createPartialOptions({ brk }) {
|
||||
tree: [
|
||||
createCohortFolderBasicWithoutMarketCap(ctx, {
|
||||
name: "Compare",
|
||||
title: "Amount Range",
|
||||
title: "Size Range",
|
||||
list: utxosAmountRanges,
|
||||
}),
|
||||
...utxosAmountRanges.map(mapBasicWithoutMarketCap),
|
||||
@@ -214,29 +197,29 @@ export function createPartialOptions({ brk }) {
|
||||
],
|
||||
},
|
||||
|
||||
// Balance cohorts (Address balance)
|
||||
// Balances cohorts (Address balance)
|
||||
{
|
||||
name: "Balance",
|
||||
name: "Balances",
|
||||
tree: [
|
||||
// Under (< X sats)
|
||||
// Less Than (< X sats)
|
||||
{
|
||||
name: "Under",
|
||||
name: "Less Than",
|
||||
tree: [
|
||||
createAddressCohortFolder(ctx, {
|
||||
name: "Compare",
|
||||
title: "Balance Under",
|
||||
title: "Balance Less Than",
|
||||
list: addressesUnderAmount,
|
||||
}),
|
||||
...addressesUnderAmount.map(mapAddressCohorts),
|
||||
],
|
||||
},
|
||||
// Above (≥ X sats)
|
||||
// More Than (≥ X sats)
|
||||
{
|
||||
name: "Above",
|
||||
name: "More Than",
|
||||
tree: [
|
||||
createAddressCohortFolder(ctx, {
|
||||
name: "Compare",
|
||||
title: "Balance Above",
|
||||
title: "Balance More Than",
|
||||
list: addressesAboveAmount,
|
||||
}),
|
||||
...addressesAboveAmount.map(mapAddressCohorts),
|
||||
@@ -257,6 +240,20 @@ export function createPartialOptions({ brk }) {
|
||||
],
|
||||
},
|
||||
|
||||
// Script Types - addressable types have addrCount, others don't
|
||||
{
|
||||
name: "Script Types",
|
||||
tree: [
|
||||
createCohortFolderAddress(ctx, {
|
||||
name: "Compare",
|
||||
title: "Script Type",
|
||||
list: typeAddressable,
|
||||
}),
|
||||
...typeAddressable.map(mapAddress),
|
||||
...typeOther.map(mapBasicWithoutMarketCap),
|
||||
],
|
||||
},
|
||||
|
||||
// Epochs - CohortBasicWithoutMarketCap (no RelToMarketCap)
|
||||
{
|
||||
name: "Epochs",
|
||||
@@ -285,8 +282,13 @@ export function createPartialOptions({ brk }) {
|
||||
],
|
||||
},
|
||||
|
||||
// Cointime section
|
||||
createCointimeSection(ctx),
|
||||
// Research section
|
||||
{
|
||||
name: "Research",
|
||||
tree: [
|
||||
createCointimeSection(ctx),
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
|
||||
@@ -166,7 +166,7 @@ export function createRatioChart(ctx, { title, price, ratio, color, name }) {
|
||||
name: name ?? "ratio",
|
||||
title: title(name ?? "Ratio"),
|
||||
top: [
|
||||
line({ metric: price, name: "price", color, unit: Unit.usd }),
|
||||
line({ metric: price, name: "Price", color, unit: Unit.usd }),
|
||||
...percentileUsdMap(colors, ratio).map(({ name, prop, color }) =>
|
||||
line({
|
||||
metric: prop,
|
||||
@@ -221,7 +221,7 @@ export function createZScoresFolder(
|
||||
const sdPats = sdPatterns(ratio);
|
||||
|
||||
return {
|
||||
name: "ZScores",
|
||||
name: "Z-Scores",
|
||||
tree: [
|
||||
{
|
||||
name: "Compare",
|
||||
|
||||
@@ -41,6 +41,8 @@ function walk(node, map, path) {
|
||||
kn === "outputtype" ||
|
||||
kn === "heighttopool" ||
|
||||
kn === "txid" ||
|
||||
kn.startsWith("satblocks") ||
|
||||
kn.startsWith("satdays") ||
|
||||
kn.endsWith("state") ||
|
||||
kn.endsWith("index") ||
|
||||
kn.endsWith("indexes") ||
|
||||
|
||||
@@ -40,10 +40,11 @@ a {
|
||||
&[target="_blank"]::after {
|
||||
color: var(--off-color);
|
||||
content: "↗";
|
||||
align-self: baseline;
|
||||
font-weight: 300;
|
||||
font-weight: 400;
|
||||
font-size: 1rem;
|
||||
|
||||
margin-left: 0.25rem;
|
||||
margin-top: 0.1rem;
|
||||
margin-left: 0.375rem;
|
||||
line-height: 1;
|
||||
|
||||
&:hover {
|
||||
|
||||
Reference in New Issue
Block a user