@taphubhq/sdk-core 0.27.0 → 0.28.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -60,6 +60,8 @@ __export(index_exports, {
60
60
  calculateProbHit: () => calculateProbHit,
61
61
  calculateProbWin: () => calculateProbWin,
62
62
  calculateProbWin_v2: () => calculateProbWin_v2,
63
+ coefMultBandIndex: () => coefMultBandIndex,
64
+ coefMultiplierAt: () => coefMultiplierAt,
63
65
  computeBaseline: () => computeBaseline,
64
66
  errorFunction: () => errorFunction,
65
67
  isCancelled: () => isCancelled,
@@ -1254,7 +1256,9 @@ function normaliseConstraints(node) {
1254
1256
  priceMinRange: node.priceMinRange,
1255
1257
  priceMaxRange: node.priceMaxRange,
1256
1258
  coefMults: node.coefMults,
1257
- maxCoef: node.maxCoef
1259
+ maxCoef: node.maxCoef,
1260
+ // bid-260819: pass through untouched — pricing consumes it as-is.
1261
+ coefMultsMatrix: node.coefMultsMatrix ?? null
1258
1262
  };
1259
1263
  }
1260
1264
  function normaliseCandles(list) {
@@ -1307,7 +1311,7 @@ var PAIR_QUERY = `query AgencyPair($pairId: ID!) {
1307
1311
  id pair { id pair source thumb } status createdAt
1308
1312
  config {
1309
1313
  gridConfig { cellSizeTime cellSizeValue candleSize baseline baselineTime }
1310
- constraints { minBetTime maxBetTime slippage priceMinRange priceMaxRange coefMults maxCoef }
1314
+ constraints { minBetTime maxBetTime slippage priceMinRange priceMaxRange coefMults maxCoef coefMultsMatrix { timeBandsSec rows } }
1311
1315
  acceptableBids minBidAmount maxBidAmount
1312
1316
  bidCancelRefundRate bidCancelMinSeconds
1313
1317
  }
@@ -3847,6 +3851,40 @@ function calculateProbWin_v2(time1, time2, _price1, price2, creationTime, curren
3847
3851
  const prob = 1 - normalCDF(z);
3848
3852
  return Math.max(0, Math.min(1, prob));
3849
3853
  }
3854
+ function coefMultBandIndex(timeBandsSec, timeToStartSec) {
3855
+ for (let i = 0; i < timeBandsSec.length; i++) {
3856
+ if (timeToStartSec <= timeBandsSec[i]) return i;
3857
+ }
3858
+ return timeBandsSec.length;
3859
+ }
3860
+ function coefMultiplierAt(timeBandsSec, row, timeToStartSec) {
3861
+ if (row.length === 0) return 1;
3862
+ if (row.length === 1 || timeBandsSec.length === 0) return row[0];
3863
+ let valueCount = row.length;
3864
+ if (valueCount > timeBandsSec.length + 1) valueCount = timeBandsSec.length + 1;
3865
+ const edges = timeBandsSec.slice(0, valueCount - 1);
3866
+ const anchors = new Array(valueCount);
3867
+ anchors[0] = edges[0] / 2;
3868
+ for (let i = 1; i < valueCount - 1; i++) {
3869
+ anchors[i] = (edges[i - 1] + edges[i]) / 2;
3870
+ }
3871
+ const last = valueCount - 1;
3872
+ if (edges.length >= 2) {
3873
+ anchors[last] = edges[last - 1] + (edges[last - 1] - edges[last - 2]) / 2;
3874
+ } else {
3875
+ anchors[last] = 1.5 * edges[0];
3876
+ }
3877
+ const t = timeToStartSec;
3878
+ if (t <= anchors[0]) return row[0];
3879
+ if (t >= anchors[last]) return row[last];
3880
+ for (let i = 1; i <= last; i++) {
3881
+ if (t <= anchors[i]) {
3882
+ const frac = (t - anchors[i - 1]) / (anchors[i] - anchors[i - 1]);
3883
+ return row[i - 1] + (row[i] - row[i - 1]) * frac;
3884
+ }
3885
+ }
3886
+ return row[last];
3887
+ }
3850
3888
  function simpsonForHit(f, a, b, eps = 3e-5, maxDepth = 14) {
3851
3889
  function simpsonRule(a2, b2) {
3852
3890
  const c = (a2 + b2) / 2;
@@ -3916,7 +3954,7 @@ function calculateCoefficientWrapper(params) {
3916
3954
  candleClose,
3917
3955
  volatility,
3918
3956
  coefMults,
3919
- cellSizeTime,
3957
+ coefMultsMatrix,
3920
3958
  minCoef
3921
3959
  } = params;
3922
3960
  const currentPrice = candleClose;
@@ -3933,22 +3971,46 @@ function calculateCoefficientWrapper(params) {
3933
3971
  if (probability <= 0) return Number.POSITIVE_INFINITY;
3934
3972
  const rawCoef = 1 / probability;
3935
3973
  const rawIndex = rawCoef < 1 ? 0 : Math.floor(Math.log2(rawCoef));
3936
- const coefMultIndex = Math.min(rawIndex, coefMults.length - 1);
3937
- const multiplier = coefMults[coefMultIndex] || 1;
3938
- const timeRatio = cellSizeTime;
3939
- const adjustedProb = probability * (timeRatio / 5);
3940
- if (adjustedProb <= 0) return Number.POSITIVE_INFINITY;
3974
+ let multiplier = 1;
3975
+ if (coefMultsMatrix && coefMultsMatrix.rows.length > 0) {
3976
+ const bucketIndex = Math.min(rawIndex, coefMultsMatrix.rows.length - 1);
3977
+ const row = coefMultsMatrix.rows[bucketIndex];
3978
+ if (row && row.length > 0) {
3979
+ multiplier = coefMultiplierAt(coefMultsMatrix.timeBandsSec, row, time1 - candleTime);
3980
+ }
3981
+ } else {
3982
+ const coefMultIndex = Math.min(rawIndex, coefMults.length - 1);
3983
+ multiplier = coefMults[coefMultIndex] || 1;
3984
+ }
3941
3985
  const floor = typeof minCoef === "number" && minCoef > 0 ? minCoef : 1;
3942
- const finalCoef = Math.max(floor, multiplier / adjustedProb);
3986
+ const finalCoef = Math.max(floor, multiplier / probability);
3943
3987
  return roundCoefToSignificantDigits(finalCoef);
3944
3988
  }
3945
3989
  function roundCoefToSignificantDigits(value) {
3946
3990
  if (!Number.isFinite(value) || value <= 0) return value;
3947
- const magnitude = Math.floor(Math.log10(value));
3948
- const leadingDigit = Math.floor(value / 10 ** magnitude);
3949
- const sigDigits = leadingDigit === 1 ? 3 : 2;
3950
- const factor = 10 ** (sigDigits - magnitude - 1);
3951
- return Math.round(value * factor) / factor;
3991
+ let exponent = 0;
3992
+ let scaled = value;
3993
+ while (scaled >= 10) {
3994
+ scaled /= 10;
3995
+ exponent++;
3996
+ }
3997
+ while (scaled < 1) {
3998
+ scaled *= 10;
3999
+ exponent--;
4000
+ }
4001
+ const digits = Math.floor(scaled) === 1 ? 3 : 2;
4002
+ const factorExponent = digits - exponent - 1;
4003
+ if (factorExponent >= 0) {
4004
+ const factor = exactPowerOfTen(factorExponent);
4005
+ return Math.round(value * factor) / factor;
4006
+ }
4007
+ const divisor = exactPowerOfTen(-factorExponent);
4008
+ return Math.round(value / divisor) * divisor;
4009
+ }
4010
+ function exactPowerOfTen(n) {
4011
+ let power = 1;
4012
+ for (let i = 0; i < n; i++) power *= 10;
4013
+ return power;
3952
4014
  }
3953
4015
  function computeBaseline(candleClose, candleTimeSec, cellSizeValue, cellSizeTime, candleSize) {
3954
4016
  const baseline = Math.floor(candleClose / cellSizeValue) * cellSizeValue;
@@ -3988,6 +4050,8 @@ function computeBaseline(candleClose, candleTimeSec, cellSizeValue, cellSizeTime
3988
4050
  calculateProbHit,
3989
4051
  calculateProbWin,
3990
4052
  calculateProbWin_v2,
4053
+ coefMultBandIndex,
4054
+ coefMultiplierAt,
3991
4055
  computeBaseline,
3992
4056
  errorFunction,
3993
4057
  isCancelled,
package/dist/index.d.mts CHANGED
@@ -866,6 +866,11 @@ interface Constraints {
866
866
  priceMaxRange: number;
867
867
  coefMults: number[];
868
868
  maxCoef: number;
869
+ coefMultsMatrix?: CoefMultsMatrix$1 | null;
870
+ }
871
+ interface CoefMultsMatrix$1 {
872
+ timeBandsSec: number[];
873
+ rows: number[][];
869
874
  }
870
875
  interface PairInfo {
871
876
  /**
@@ -1936,10 +1941,15 @@ interface CoefficientInput {
1936
1941
  candleClose: number;
1937
1942
  volatility: number;
1938
1943
  coefMults: number[];
1939
- cellSizeTime: number;
1940
- candleSize: number;
1944
+ coefMultsMatrix?: CoefMultsMatrix | null;
1941
1945
  minCoef?: number;
1942
1946
  }
1947
+ interface CoefMultsMatrix {
1948
+ timeBandsSec: number[];
1949
+ rows: number[][];
1950
+ }
1951
+ declare function coefMultBandIndex(timeBandsSec: number[], timeToStartSec: number): number;
1952
+ declare function coefMultiplierAt(timeBandsSec: number[], row: number[], timeToStartSec: number): number;
1943
1953
  /**
1944
1954
  * First-passage hitting probability: chance the price visits [price1, price2]
1945
1955
  * at any point during [time1, time2], given GBM dynamics.
@@ -1956,4 +1966,4 @@ declare function computeBaseline(candleClose: number, candleTimeSec: number, cel
1956
1966
  baselineTime: number;
1957
1967
  };
1958
1968
 
1959
- export { type AgencyPairFilter, AgencyPairModule, type AgencyPairStats, type AgencyPairStatus, AuthModule, type BackendHealth, type Bid, type BidCellCandle, BidModule, type BidStatus, CANDLE_EVENT, type CancelBidResult, type Candle, type CandleEventType, type CoefficientInput, type Constraints, type Currency, DEFAULT_CHART_HISTORY_LIMIT, DEFAULT_PROBE_TTL_SECONDS, DEFAULT_REGION, type ErrorMessageCatalog, type ErrorMessageMeta, type ErrorMessagesResponse, GameChannel, type GameConfig, type GridConfig, KNOWN_REGIONS, type KnownRegion, type LeaderboardEntry, LeaderboardModule, type LeaderboardPeriod, type LeaderboardSortBy, LocaleModule, type LocaleRefreshResult, type LocaleResponse, type LocaleTranslations, type LoginResult, type Me, MigrationChannel, type MigrationChannelEvents, type MigrationCompletedEvent, type MqttAcceptedBid, type MqttAgencyPairStatsEvent, type MqttAuthConfig, type MqttBalanceEvent, type MqttBidAcceptedEvent, type MqttBidLostEvent, type MqttBidWonEvent, type MqttCandleEvent, type MqttCellCandleFinalEvent, type MqttConfigEvent, type MqttIdealConfigEvent, type MqttWalletBalanceEvent, type MyRank, type NetworkLevel, type NetworkQuality, NetworkQualityMonitor, type Pair, type PairInfo, PairModule, type PlaceBidInput, type ProbeNearestRegionOptions, REGION_PROBE_CACHE_KEY, type RankBoard, type RankEntry, type RankPeriod, type RankSort, RealtimeModule, type RefreshTokenResult, type RegionDomainMap, type Sample, type SampleReason, type SignalSource, type SortDir, TaphubAuthError, TaphubClient, type TaphubClientConfig, TaphubError, TaphubEventBus, type TaphubEventMap, TaphubNetworkError, TaphubServerError, TaphubSlippageError, TaphubStorage, type TaphubStorageAdapter, TaphubValidationError, type User, UserBidsChannel, type UserBidsChannelEvents, UserModule, type UserPnL, type UserPnLPeriod, type Wallet as UserWallet, type Wallet$1 as Wallet, type WalletBalanceReason, WalletChannel, adaptiveSimpson, autoDetectStorage, calculateCoefficientWrapper, calculateProbHit, calculateProbWin, calculateProbWin_v2, computeBaseline, errorFunction, isCancelled, isKnownRegion, isLoss, isPending, isTerminal, isWin, normalCDF, normalPDF, normaliseLang, pairIdFromBidResultTopic, probeNearestRegion, resolveRegionBaseUrl, roundCoefToSignificantDigits };
1969
+ export { type AgencyPairFilter, AgencyPairModule, type AgencyPairStats, type AgencyPairStatus, AuthModule, type BackendHealth, type Bid, type BidCellCandle, BidModule, type BidStatus, CANDLE_EVENT, type CancelBidResult, type Candle, type CandleEventType, type CoefMultsMatrix, type CoefficientInput, type Constraints, type Currency, DEFAULT_CHART_HISTORY_LIMIT, DEFAULT_PROBE_TTL_SECONDS, DEFAULT_REGION, type ErrorMessageCatalog, type ErrorMessageMeta, type ErrorMessagesResponse, GameChannel, type GameConfig, type GridConfig, KNOWN_REGIONS, type KnownRegion, type LeaderboardEntry, LeaderboardModule, type LeaderboardPeriod, type LeaderboardSortBy, LocaleModule, type LocaleRefreshResult, type LocaleResponse, type LocaleTranslations, type LoginResult, type Me, MigrationChannel, type MigrationChannelEvents, type MigrationCompletedEvent, type MqttAcceptedBid, type MqttAgencyPairStatsEvent, type MqttAuthConfig, type MqttBalanceEvent, type MqttBidAcceptedEvent, type MqttBidLostEvent, type MqttBidWonEvent, type MqttCandleEvent, type MqttCellCandleFinalEvent, type MqttConfigEvent, type MqttIdealConfigEvent, type MqttWalletBalanceEvent, type MyRank, type NetworkLevel, type NetworkQuality, NetworkQualityMonitor, type Pair, type PairInfo, PairModule, type PlaceBidInput, type ProbeNearestRegionOptions, REGION_PROBE_CACHE_KEY, type RankBoard, type RankEntry, type RankPeriod, type RankSort, RealtimeModule, type RefreshTokenResult, type RegionDomainMap, type Sample, type SampleReason, type SignalSource, type SortDir, TaphubAuthError, TaphubClient, type TaphubClientConfig, TaphubError, TaphubEventBus, type TaphubEventMap, TaphubNetworkError, TaphubServerError, TaphubSlippageError, TaphubStorage, type TaphubStorageAdapter, TaphubValidationError, type User, UserBidsChannel, type UserBidsChannelEvents, UserModule, type UserPnL, type UserPnLPeriod, type Wallet as UserWallet, type Wallet$1 as Wallet, type WalletBalanceReason, WalletChannel, adaptiveSimpson, autoDetectStorage, calculateCoefficientWrapper, calculateProbHit, calculateProbWin, calculateProbWin_v2, coefMultBandIndex, coefMultiplierAt, computeBaseline, errorFunction, isCancelled, isKnownRegion, isLoss, isPending, isTerminal, isWin, normalCDF, normalPDF, normaliseLang, pairIdFromBidResultTopic, probeNearestRegion, resolveRegionBaseUrl, roundCoefToSignificantDigits };
package/dist/index.d.ts CHANGED
@@ -866,6 +866,11 @@ interface Constraints {
866
866
  priceMaxRange: number;
867
867
  coefMults: number[];
868
868
  maxCoef: number;
869
+ coefMultsMatrix?: CoefMultsMatrix$1 | null;
870
+ }
871
+ interface CoefMultsMatrix$1 {
872
+ timeBandsSec: number[];
873
+ rows: number[][];
869
874
  }
870
875
  interface PairInfo {
871
876
  /**
@@ -1936,10 +1941,15 @@ interface CoefficientInput {
1936
1941
  candleClose: number;
1937
1942
  volatility: number;
1938
1943
  coefMults: number[];
1939
- cellSizeTime: number;
1940
- candleSize: number;
1944
+ coefMultsMatrix?: CoefMultsMatrix | null;
1941
1945
  minCoef?: number;
1942
1946
  }
1947
+ interface CoefMultsMatrix {
1948
+ timeBandsSec: number[];
1949
+ rows: number[][];
1950
+ }
1951
+ declare function coefMultBandIndex(timeBandsSec: number[], timeToStartSec: number): number;
1952
+ declare function coefMultiplierAt(timeBandsSec: number[], row: number[], timeToStartSec: number): number;
1943
1953
  /**
1944
1954
  * First-passage hitting probability: chance the price visits [price1, price2]
1945
1955
  * at any point during [time1, time2], given GBM dynamics.
@@ -1956,4 +1966,4 @@ declare function computeBaseline(candleClose: number, candleTimeSec: number, cel
1956
1966
  baselineTime: number;
1957
1967
  };
1958
1968
 
1959
- export { type AgencyPairFilter, AgencyPairModule, type AgencyPairStats, type AgencyPairStatus, AuthModule, type BackendHealth, type Bid, type BidCellCandle, BidModule, type BidStatus, CANDLE_EVENT, type CancelBidResult, type Candle, type CandleEventType, type CoefficientInput, type Constraints, type Currency, DEFAULT_CHART_HISTORY_LIMIT, DEFAULT_PROBE_TTL_SECONDS, DEFAULT_REGION, type ErrorMessageCatalog, type ErrorMessageMeta, type ErrorMessagesResponse, GameChannel, type GameConfig, type GridConfig, KNOWN_REGIONS, type KnownRegion, type LeaderboardEntry, LeaderboardModule, type LeaderboardPeriod, type LeaderboardSortBy, LocaleModule, type LocaleRefreshResult, type LocaleResponse, type LocaleTranslations, type LoginResult, type Me, MigrationChannel, type MigrationChannelEvents, type MigrationCompletedEvent, type MqttAcceptedBid, type MqttAgencyPairStatsEvent, type MqttAuthConfig, type MqttBalanceEvent, type MqttBidAcceptedEvent, type MqttBidLostEvent, type MqttBidWonEvent, type MqttCandleEvent, type MqttCellCandleFinalEvent, type MqttConfigEvent, type MqttIdealConfigEvent, type MqttWalletBalanceEvent, type MyRank, type NetworkLevel, type NetworkQuality, NetworkQualityMonitor, type Pair, type PairInfo, PairModule, type PlaceBidInput, type ProbeNearestRegionOptions, REGION_PROBE_CACHE_KEY, type RankBoard, type RankEntry, type RankPeriod, type RankSort, RealtimeModule, type RefreshTokenResult, type RegionDomainMap, type Sample, type SampleReason, type SignalSource, type SortDir, TaphubAuthError, TaphubClient, type TaphubClientConfig, TaphubError, TaphubEventBus, type TaphubEventMap, TaphubNetworkError, TaphubServerError, TaphubSlippageError, TaphubStorage, type TaphubStorageAdapter, TaphubValidationError, type User, UserBidsChannel, type UserBidsChannelEvents, UserModule, type UserPnL, type UserPnLPeriod, type Wallet as UserWallet, type Wallet$1 as Wallet, type WalletBalanceReason, WalletChannel, adaptiveSimpson, autoDetectStorage, calculateCoefficientWrapper, calculateProbHit, calculateProbWin, calculateProbWin_v2, computeBaseline, errorFunction, isCancelled, isKnownRegion, isLoss, isPending, isTerminal, isWin, normalCDF, normalPDF, normaliseLang, pairIdFromBidResultTopic, probeNearestRegion, resolveRegionBaseUrl, roundCoefToSignificantDigits };
1969
+ export { type AgencyPairFilter, AgencyPairModule, type AgencyPairStats, type AgencyPairStatus, AuthModule, type BackendHealth, type Bid, type BidCellCandle, BidModule, type BidStatus, CANDLE_EVENT, type CancelBidResult, type Candle, type CandleEventType, type CoefMultsMatrix, type CoefficientInput, type Constraints, type Currency, DEFAULT_CHART_HISTORY_LIMIT, DEFAULT_PROBE_TTL_SECONDS, DEFAULT_REGION, type ErrorMessageCatalog, type ErrorMessageMeta, type ErrorMessagesResponse, GameChannel, type GameConfig, type GridConfig, KNOWN_REGIONS, type KnownRegion, type LeaderboardEntry, LeaderboardModule, type LeaderboardPeriod, type LeaderboardSortBy, LocaleModule, type LocaleRefreshResult, type LocaleResponse, type LocaleTranslations, type LoginResult, type Me, MigrationChannel, type MigrationChannelEvents, type MigrationCompletedEvent, type MqttAcceptedBid, type MqttAgencyPairStatsEvent, type MqttAuthConfig, type MqttBalanceEvent, type MqttBidAcceptedEvent, type MqttBidLostEvent, type MqttBidWonEvent, type MqttCandleEvent, type MqttCellCandleFinalEvent, type MqttConfigEvent, type MqttIdealConfigEvent, type MqttWalletBalanceEvent, type MyRank, type NetworkLevel, type NetworkQuality, NetworkQualityMonitor, type Pair, type PairInfo, PairModule, type PlaceBidInput, type ProbeNearestRegionOptions, REGION_PROBE_CACHE_KEY, type RankBoard, type RankEntry, type RankPeriod, type RankSort, RealtimeModule, type RefreshTokenResult, type RegionDomainMap, type Sample, type SampleReason, type SignalSource, type SortDir, TaphubAuthError, TaphubClient, type TaphubClientConfig, TaphubError, TaphubEventBus, type TaphubEventMap, TaphubNetworkError, TaphubServerError, TaphubSlippageError, TaphubStorage, type TaphubStorageAdapter, TaphubValidationError, type User, UserBidsChannel, type UserBidsChannelEvents, UserModule, type UserPnL, type UserPnLPeriod, type Wallet as UserWallet, type Wallet$1 as Wallet, type WalletBalanceReason, WalletChannel, adaptiveSimpson, autoDetectStorage, calculateCoefficientWrapper, calculateProbHit, calculateProbWin, calculateProbWin_v2, coefMultBandIndex, coefMultiplierAt, computeBaseline, errorFunction, isCancelled, isKnownRegion, isLoss, isPending, isTerminal, isWin, normalCDF, normalPDF, normaliseLang, pairIdFromBidResultTopic, probeNearestRegion, resolveRegionBaseUrl, roundCoefToSignificantDigits };
package/dist/index.js CHANGED
@@ -1174,7 +1174,9 @@ function normaliseConstraints(node) {
1174
1174
  priceMinRange: node.priceMinRange,
1175
1175
  priceMaxRange: node.priceMaxRange,
1176
1176
  coefMults: node.coefMults,
1177
- maxCoef: node.maxCoef
1177
+ maxCoef: node.maxCoef,
1178
+ // bid-260819: pass through untouched — pricing consumes it as-is.
1179
+ coefMultsMatrix: node.coefMultsMatrix ?? null
1178
1180
  };
1179
1181
  }
1180
1182
  function normaliseCandles(list) {
@@ -1227,7 +1229,7 @@ var PAIR_QUERY = `query AgencyPair($pairId: ID!) {
1227
1229
  id pair { id pair source thumb } status createdAt
1228
1230
  config {
1229
1231
  gridConfig { cellSizeTime cellSizeValue candleSize baseline baselineTime }
1230
- constraints { minBetTime maxBetTime slippage priceMinRange priceMaxRange coefMults maxCoef }
1232
+ constraints { minBetTime maxBetTime slippage priceMinRange priceMaxRange coefMults maxCoef coefMultsMatrix { timeBandsSec rows } }
1231
1233
  acceptableBids minBidAmount maxBidAmount
1232
1234
  bidCancelRefundRate bidCancelMinSeconds
1233
1235
  }
@@ -3767,6 +3769,40 @@ function calculateProbWin_v2(time1, time2, _price1, price2, creationTime, curren
3767
3769
  const prob = 1 - normalCDF(z);
3768
3770
  return Math.max(0, Math.min(1, prob));
3769
3771
  }
3772
+ function coefMultBandIndex(timeBandsSec, timeToStartSec) {
3773
+ for (let i = 0; i < timeBandsSec.length; i++) {
3774
+ if (timeToStartSec <= timeBandsSec[i]) return i;
3775
+ }
3776
+ return timeBandsSec.length;
3777
+ }
3778
+ function coefMultiplierAt(timeBandsSec, row, timeToStartSec) {
3779
+ if (row.length === 0) return 1;
3780
+ if (row.length === 1 || timeBandsSec.length === 0) return row[0];
3781
+ let valueCount = row.length;
3782
+ if (valueCount > timeBandsSec.length + 1) valueCount = timeBandsSec.length + 1;
3783
+ const edges = timeBandsSec.slice(0, valueCount - 1);
3784
+ const anchors = new Array(valueCount);
3785
+ anchors[0] = edges[0] / 2;
3786
+ for (let i = 1; i < valueCount - 1; i++) {
3787
+ anchors[i] = (edges[i - 1] + edges[i]) / 2;
3788
+ }
3789
+ const last = valueCount - 1;
3790
+ if (edges.length >= 2) {
3791
+ anchors[last] = edges[last - 1] + (edges[last - 1] - edges[last - 2]) / 2;
3792
+ } else {
3793
+ anchors[last] = 1.5 * edges[0];
3794
+ }
3795
+ const t = timeToStartSec;
3796
+ if (t <= anchors[0]) return row[0];
3797
+ if (t >= anchors[last]) return row[last];
3798
+ for (let i = 1; i <= last; i++) {
3799
+ if (t <= anchors[i]) {
3800
+ const frac = (t - anchors[i - 1]) / (anchors[i] - anchors[i - 1]);
3801
+ return row[i - 1] + (row[i] - row[i - 1]) * frac;
3802
+ }
3803
+ }
3804
+ return row[last];
3805
+ }
3770
3806
  function simpsonForHit(f, a, b, eps = 3e-5, maxDepth = 14) {
3771
3807
  function simpsonRule(a2, b2) {
3772
3808
  const c = (a2 + b2) / 2;
@@ -3836,7 +3872,7 @@ function calculateCoefficientWrapper(params) {
3836
3872
  candleClose,
3837
3873
  volatility,
3838
3874
  coefMults,
3839
- cellSizeTime,
3875
+ coefMultsMatrix,
3840
3876
  minCoef
3841
3877
  } = params;
3842
3878
  const currentPrice = candleClose;
@@ -3853,22 +3889,46 @@ function calculateCoefficientWrapper(params) {
3853
3889
  if (probability <= 0) return Number.POSITIVE_INFINITY;
3854
3890
  const rawCoef = 1 / probability;
3855
3891
  const rawIndex = rawCoef < 1 ? 0 : Math.floor(Math.log2(rawCoef));
3856
- const coefMultIndex = Math.min(rawIndex, coefMults.length - 1);
3857
- const multiplier = coefMults[coefMultIndex] || 1;
3858
- const timeRatio = cellSizeTime;
3859
- const adjustedProb = probability * (timeRatio / 5);
3860
- if (adjustedProb <= 0) return Number.POSITIVE_INFINITY;
3892
+ let multiplier = 1;
3893
+ if (coefMultsMatrix && coefMultsMatrix.rows.length > 0) {
3894
+ const bucketIndex = Math.min(rawIndex, coefMultsMatrix.rows.length - 1);
3895
+ const row = coefMultsMatrix.rows[bucketIndex];
3896
+ if (row && row.length > 0) {
3897
+ multiplier = coefMultiplierAt(coefMultsMatrix.timeBandsSec, row, time1 - candleTime);
3898
+ }
3899
+ } else {
3900
+ const coefMultIndex = Math.min(rawIndex, coefMults.length - 1);
3901
+ multiplier = coefMults[coefMultIndex] || 1;
3902
+ }
3861
3903
  const floor = typeof minCoef === "number" && minCoef > 0 ? minCoef : 1;
3862
- const finalCoef = Math.max(floor, multiplier / adjustedProb);
3904
+ const finalCoef = Math.max(floor, multiplier / probability);
3863
3905
  return roundCoefToSignificantDigits(finalCoef);
3864
3906
  }
3865
3907
  function roundCoefToSignificantDigits(value) {
3866
3908
  if (!Number.isFinite(value) || value <= 0) return value;
3867
- const magnitude = Math.floor(Math.log10(value));
3868
- const leadingDigit = Math.floor(value / 10 ** magnitude);
3869
- const sigDigits = leadingDigit === 1 ? 3 : 2;
3870
- const factor = 10 ** (sigDigits - magnitude - 1);
3871
- return Math.round(value * factor) / factor;
3909
+ let exponent = 0;
3910
+ let scaled = value;
3911
+ while (scaled >= 10) {
3912
+ scaled /= 10;
3913
+ exponent++;
3914
+ }
3915
+ while (scaled < 1) {
3916
+ scaled *= 10;
3917
+ exponent--;
3918
+ }
3919
+ const digits = Math.floor(scaled) === 1 ? 3 : 2;
3920
+ const factorExponent = digits - exponent - 1;
3921
+ if (factorExponent >= 0) {
3922
+ const factor = exactPowerOfTen(factorExponent);
3923
+ return Math.round(value * factor) / factor;
3924
+ }
3925
+ const divisor = exactPowerOfTen(-factorExponent);
3926
+ return Math.round(value / divisor) * divisor;
3927
+ }
3928
+ function exactPowerOfTen(n) {
3929
+ let power = 1;
3930
+ for (let i = 0; i < n; i++) power *= 10;
3931
+ return power;
3872
3932
  }
3873
3933
  function computeBaseline(candleClose, candleTimeSec, cellSizeValue, cellSizeTime, candleSize) {
3874
3934
  const baseline = Math.floor(candleClose / cellSizeValue) * cellSizeValue;
@@ -3907,6 +3967,8 @@ export {
3907
3967
  calculateProbHit,
3908
3968
  calculateProbWin,
3909
3969
  calculateProbWin_v2,
3970
+ coefMultBandIndex,
3971
+ coefMultiplierAt,
3910
3972
  computeBaseline,
3911
3973
  errorFunction,
3912
3974
  isCancelled,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@taphubhq/sdk-core",
3
- "version": "0.27.0",
3
+ "version": "0.28.0",
4
4
  "description": "Core SDK for building on the TabHub platform",
5
5
  "license": "MIT",
6
6
  "main": "./dist/index.cjs",