Problem 602131 · medium · Level 06 Heuristics & Optimization

When the Fast Average Overtakes the Slow One

py-advanced-iteration · py-stdlib · itertools.tee · itertools.accumulate · moving averages

A trading dashboard watches an endless feed of whole-cent prices and flags every moment at which the average of the last short prices moves above or below the average of the last long prices.

For each index i >= long - 1 of the feed (counting from 0), let S(i) be the mean of the short prices ending at index i, and L(i) the mean of the long prices ending there. At index i the feed is above when S(i) > L(i) and below otherwise (ties count as below). Write a generator function crossings(prices, short, long) that yields (i, "up") whenever the feed is above at i but was below at i - 1, and (i, "down") in the opposite case. Index long - 1 only sets the starting state; it never produces an event.

The feed is endless, so the tests take events with first(gen, n). The dashboard must react as soon as a price arrives: the event at index i must be yielded after reading exactly i + 1 prices, never more. reads_until(crossings, seed, short, long, k) takes k events from a generated feed and returns the last one together with the number of prices read. Other helpers: stream(items) (a finite one-pass feed, after which your generator ends) and ticker(seed).

Examples

Input:  first(crossings(stream([10, 11, 12, 11, 9, 8, 9, 12, 14, 13, 10, 9]), 2, 4), 10)
Output: [(4, "down"), (7, "up"), (10, "down")]
Explanation: at index 3 the fast mean 11.5 is above the slow mean 11.0; at index 4 it is 10.0 against 10.75.

Input:  reads_until(crossings, 1, 5, 20, 3)
Output: ((87, "up"), 88)

Constraints

  • 1 <= short < long <= 500; prices are positive integers.
  • Compare the averages exactly (the prices are integers, so the means can be compared without rounding errors).

Goals

  • Split one stream into several independent iterators with `itertools.tee`
  • Compute window sums from running totals with `accumulate` and a lagged copy made by `islice`
  • Chain lazy stages so that no stage reads further ahead than the result needs
Starting Python…