* Converts a float data index to an interpolated timestamp. * This allows sub-bar precision for smooth freehand drawings. * Supports extrapolation beyond the data range (drawing in the "future"). * @param floatIndex - A floating point index (e.g., 42.75) * @returns An interpolated timest
(floatIndex: number)
| 1077 | * @returns An interpolated timestamp between two bars |
| 1078 | */ |
| 1079 | floatIndexToTimestamp (floatIndex: number): Nullable<number> { |
| 1080 | const length = this._dataList.length |
| 1081 | if (length === 0) { |
| 1082 | return null |
| 1083 | } |
| 1084 | |
| 1085 | const lastIndex = length - 1 |
| 1086 | |
| 1087 | // Handle float index beyond the last bar (extrapolate into the future) |
| 1088 | if (floatIndex > lastIndex && length >= 2) { |
| 1089 | const lastTimestamp = this._dataList[lastIndex].timestamp |
| 1090 | const secondLastTimestamp = this._dataList[lastIndex - 1].timestamp |
| 1091 | const barDuration = lastTimestamp - secondLastTimestamp |
| 1092 | if (barDuration > 0) { |
| 1093 | const barsBeyondLast = floatIndex - lastIndex |
| 1094 | return Math.round(lastTimestamp + barsBeyondLast * barDuration) |
| 1095 | } |
| 1096 | } |
| 1097 | |
| 1098 | // Handle float index before the first bar (extrapolate into the past) |
| 1099 | if (floatIndex < 0 && length >= 2) { |
| 1100 | const firstTimestamp = this._dataList[0].timestamp |
| 1101 | const secondTimestamp = this._dataList[1].timestamp |
| 1102 | const barDuration = secondTimestamp - firstTimestamp |
| 1103 | if (barDuration > 0) { |
| 1104 | return Math.round(firstTimestamp + floatIndex * barDuration) |
| 1105 | } |
| 1106 | } |
| 1107 | |
| 1108 | // Normal case: interpolate between two bars within the data range |
| 1109 | const intIndex = Math.floor(floatIndex) |
| 1110 | const fraction = floatIndex - intIndex |
| 1111 | |
| 1112 | // Get timestamp at the integer index |
| 1113 | const timestampAtInt = this.dataIndexToTimestamp(intIndex) |
| 1114 | |
| 1115 | // If no fractional part, return the integer timestamp |
| 1116 | if (fraction === 0 || !isNumber(timestampAtInt)) { |
| 1117 | return timestampAtInt |
| 1118 | } |
| 1119 | |
| 1120 | // Get timestamp at the next index for interpolation |
| 1121 | const timestampAtNext = this.dataIndexToTimestamp(intIndex + 1) |
| 1122 | |
| 1123 | if (isNumber(timestampAtNext)) { |
| 1124 | // Linear interpolation between the two timestamps |
| 1125 | return Math.round(timestampAtInt + (timestampAtNext - timestampAtInt) * fraction) |
| 1126 | } |
| 1127 | |
| 1128 | return timestampAtInt |
| 1129 | } |
| 1130 | |
| 1131 | /** |
| 1132 | * Converts a precise timestamp to a float data index. |
no test coverage detected