Skip to content

Commit 2c6db21

Browse files
Add optional smoothing, translation
1 parent 404c307 commit 2c6db21

1 file changed

Lines changed: 44 additions & 11 deletions

File tree

pymanifold/types.py

Lines changed: 44 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -207,9 +207,11 @@ def final_probability(self) -> float:
207207
"""
208208
return self.probability_history()[1][-1]
209209

210-
def probability_at_time(self, timestamp: float) -> float:
210+
def probability_at_time(self, timestamp: float, smooth: bool = False) -> float:
211211
"""Return the probability at a given time, where time is represented as ms since origin.
212212
213+
If smooth is true, then it will give you the weighted mean of the two nearest probabilities.
214+
213215
Originally from manifoldpy/api.py, with permission, under the MIT License, under which this project is also
214216
licensed.
215217
"""
@@ -222,22 +224,53 @@ def probability_at_time(self, timestamp: float) -> float:
222224
start_guess = 0
223225
end_guess = len(times)
224226
idx = end_guess // 2
225-
while not (times[idx - 1] <= timestamp < times[idx]):
226-
if times[idx] >= timestamp:
227-
start_guess = (start_guess + idx) // 2
228-
else:
229-
end_guess = (end_guess + idx) // 2
230-
new_idx = (start_guess + end_guess) // 2
231-
if new_idx == idx:
232-
raise RuntimeError("Loop would have repeated")
233-
idx = new_idx
234-
return probs[idx]
227+
try:
228+
while not (times[idx - 1] <= timestamp < times[idx]):
229+
if times[idx] >= timestamp:
230+
start_guess = (start_guess + idx) // 2
231+
else:
232+
end_guess = (end_guess + idx) // 2
233+
new_idx = (start_guess + end_guess) // 2
234+
if new_idx == idx:
235+
raise RuntimeError("Loop would have repeated")
236+
idx = new_idx
237+
except IndexError:
238+
# this means that we fell off the edge of the probability map, so just return the nearest one
239+
if idx <= 0:
240+
return probs[0]
241+
return probs[-1]
242+
if smooth:
243+
weight_1 = 1 / abs(timestamp - times[idx - 1])
244+
weight_2 = 1 / abs(timestamp - times[idx])
245+
total_weight = weight_1 + weight_2
246+
return (probs[idx - 1] * weight_1 + probs[idx] * weight_2) / total_weight
247+
return probs[idx - 1]
235248

236249
# end section from manifoldpy
250+
def value_at_time(self, timestamp: float, smooth: bool = False) -> float:
251+
"""Get the value at a given time.
252+
253+
Note: if this is a binary market, this is the same thing as probability_at_time()
254+
"""
255+
if self.outcomeType == "BINARY":
256+
return self.probability_at_time(timestamp, smooth)
257+
assert self.min is not None
258+
assert self.max is not None
259+
return prob_to_number_cpmm1(
260+
self.probability_at_time(timestamp, smooth),
261+
self.min,
262+
self.max,
263+
bool(self.isLogScale)
264+
)
265+
237266
def probability_at_datetime(self, dt: datetime) -> float:
238267
"""Translate your datetime into one that is Manifold-compatible."""
239268
return self.probability_at_time(dt.timestamp() * 1000)
240269

270+
def value_at_datetime(self, dt: datetime) -> float:
271+
"""Translate your datetime into one that is Manifold-compatible."""
272+
return self.value_at_time(dt.timestamp() * 1000)
273+
241274

242275
@dataclass
243276
class Group(DictDeserializable):

0 commit comments

Comments
 (0)