def testIncremental_Recursive(self): size = 20 ds1 = dataseries.SequenceDataSeries() ds2 = dataseries.SequenceDataSeries() ads1, ads2 = aligned.datetime_aligned(ds1, ds2) # Align the aligned dataseries again with respect to each other. ads1, ads2 = aligned.datetime_aligned(ads1, ads2) now = datetime.datetime.now() for i in range(size): ds1.appendWithDateTime(now + datetime.timedelta(seconds=i), i) ds2.appendWithDateTime(now + datetime.timedelta(seconds=i), i) self.assertEqual(len(ads1), len(ads2)) self.assertEqual(ads1[:], ads2[:]) self.assertEqual(ads1.getDateTimes()[:], ads2.getDateTimes()[:])
def testSeqLikeOps(self): seq = range(10) ds = dataseries.SequenceDataSeries() for value in seq: ds.append(value) # Test length and every item. self.assertEqual(len(ds), len(seq)) for i in xrange(len(seq)): self.assertEqual(ds[i], seq[i]) # Test negative indices self.assertEqual(ds[-1], seq[-1]) self.assertEqual(ds[-2], seq[-2]) self.assertEqual(ds[-9], seq[-9]) # Test slices sl = slice(0, 1, 2) self.assertEqual(ds[sl], seq[sl]) sl = slice(0, 9, 2) self.assertEqual(ds[sl], seq[sl]) sl = slice(0, -1, 1) self.assertEqual(ds[sl], seq[sl]) for i in xrange(-100, 100): self.assertEqual(ds[i:], seq[i:]) for step in xrange(1, 10): for i in xrange(-100, 100): self.assertEqual(ds[i::step], seq[i::step])
def testInvalidDataSeries(self): with self.assertRaisesRegexp( Exception, "barDataSeries must be a dataseries.bards.BarDataSeries instance" ): ds = dataseries.SequenceDataSeries() linebreak.LineBreak(ds, 3, maxLen=2)
def __init__(self, dataSeries, period, div=4, interval=5): self.ma = ma.SMA(dataSeries, period) self.period = period self.div = div self.interval = interval dataSeries.getNewValueEvent().subscribe(self.__onNewValue) self.trend_data = dataseries.SequenceDataSeries()
def testInvalidDataSeries(self): with self.assertRaisesRegexp( Exception, "barDataSeries must be a dataseries.bards.BarDataSeries instance" ): ds = dataseries.SequenceDataSeries() atr.ATR(ds, 14, True)
def testMaxLen(self): ds = dataseries.SequenceDataSeries() for i in xrange(3000): ds.append(i) self.assertEqual(len(ds), 2048) self.assertEqual(ds[0], 952) self.assertEqual(ds[-1], 2999)
def __init__(self, feed, smaShort, smaLong, aroonPeriod): MyBasicStrategy.__init__(self, feed, smaShort, smaLong) self._aroon = {} self._aroonPeriod = aroonPeriod for instrument in feed.getRegisteredInstruments(): self._aroon[instrument] = dataseries.SequenceDataSeries()
def load_test_csv(path): inputSeq = [] expectedSeq = [] csvFile = open(path, "r") reader = csv.DictReader(csvFile) for row in reader: inputSeq.append(float(row["Input"])) expected = row["Expected"] if not expected: expected = None else: expected = float(expected) expectedSeq.append(expected) return (dataseries.SequenceDataSeries(inputSeq), dataseries.SequenceDataSeries(expectedSeq))
def testStockChartsBollinger(self): # Test data from http://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:bollinger_bands prices = [ 86.1557, 89.0867, 88.7829, 90.3228, 89.0671, 91.1453, 89.4397, 89.1750, 86.9302, 87.6752, 86.9596, 89.4299, 89.3221, 88.7241, 87.4497, 87.2634, 89.4985, 87.9006, 89.1260, 90.7043, 92.9001, 92.9784, 91.8021, 92.6647, 92.6843, 92.3021, 92.7725, 92.5373, 92.9490, 93.2039, 91.0669, 89.8318, 89.7435, 90.3994, 90.7387, 88.0177, 88.0867, 88.8439, 90.7781, 90.5416, 91.3894, 90.6500 ] expectedMiddle = [ 88.71, 89.05, 89.24, 89.39, 89.51, 89.69, 89.75, 89.91, 90.08, 90.38, 90.66, 90.86, 90.88, 90.91, 90.99, 91.15, 91.19, 91.12, 91.17, 91.25, 91.24, 91.17, 91.05 ] expectedUpper = [ 91.29, 91.95, 92.61, 92.93, 93.31, 93.73, 93.90, 94.27, 94.57, 94.79, 95.04, 94.91, 94.90, 94.90, 94.86, 94.67, 94.56, 94.68, 94.58, 94.53, 94.53, 94.37, 94.15 ] expectedLower = [ 86.12, 86.14, 85.87, 85.85, 85.70, 85.65, 85.59, 85.56, 85.60, 85.98, 86.27, 86.82, 86.87, 86.91, 87.12, 87.63, 87.83, 87.56, 87.76, 87.97, 87.95, 87.96, 87.95 ] seqDS = dataseries.SequenceDataSeries() bBands = bollinger.BollingerBands(seqDS, 20, 2) for value in prices: seqDS.append(value) for i in xrange(19): self.assertEqual(bBands.getMiddleBand()[i], None) self.assertEqual(bBands.getUpperBand()[i], None) self.assertEqual(bBands.getLowerBand()[i], None) for i in xrange(19, len(seqDS)): self.assertEqual(round(bBands.getMiddleBand()[i], 2), expectedMiddle[i-19]) self.assertEqual(round(bBands.getUpperBand()[i], 2), expectedUpper[i-19]) self.assertEqual(round(bBands.getLowerBand()[i], 2), expectedLower[i-19])
def testStockChartsBollinger_Bounded(self): # Test data from http://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:bollinger_bands prices = [ 86.1557, 89.0867, 88.7829, 90.3228, 89.0671, 91.1453, 89.4397, 89.1750, 86.9302, 87.6752, 86.9596, 89.4299, 89.3221, 88.7241, 87.4497, 87.2634, 89.4985, 87.9006, 89.1260, 90.7043, 92.9001, 92.9784, 91.8021, 92.6647, 92.6843, 92.3021, 92.7725, 92.5373, 92.9490, 93.2039, 91.0669, 89.8318, 89.7435, 90.3994, 90.7387, 88.0177, 88.0867, 88.8439, 90.7781, 90.5416, 91.3894, 90.6500 ] expectedMiddle = [91.24, 91.17, 91.05] expectedUpper = [94.53, 94.37, 94.15] expectedLower = [87.95, 87.96, 87.95] seqDS = dataseries.SequenceDataSeries() bBands = bollinger.BollingerBands(seqDS, 20, 2, 3) for value in prices: seqDS.append(value) for i in xrange(3): self.assertEqual(round(bBands.getMiddleBand()[i], 2), expectedMiddle[i]) self.assertEqual(round(bBands.getUpperBand()[i], 2), expectedUpper[i]) self.assertEqual(round(bBands.getLowerBand()[i], 2), expectedLower[i]) self.assertEqual(len(bBands.getMiddleBand()), 3) self.assertEqual(len(bBands.getMiddleBand()[:]), 3) self.assertEqual(len(bBands.getMiddleBand().getDateTimes()), 3) self.assertEqual(len(bBands.getUpperBand()), 3) self.assertEqual(len(bBands.getUpperBand()[:]), 3) self.assertEqual(len(bBands.getUpperBand().getDateTimes()), 3) self.assertEqual(len(bBands.getLowerBand()), 3) self.assertEqual(len(bBands.getLowerBand()[:]), 3) self.assertEqual(len(bBands.getLowerBand().getDateTimes()), 3)
def testStraightLine(self): seqDS = dataseries.SequenceDataSeries() lsReg = linreg.LeastSquaresRegression(seqDS, 3) nextDateTime = datetime.datetime(2012, 1, 1) seqDS.appendWithDateTime(nextDateTime, 1) self.assertEqual(lsReg[-1], None) nextDateTime = nextDateTime + datetime.timedelta(hours=1) seqDS.appendWithDateTime(nextDateTime, 2) self.assertEqual(lsReg[-1], None) # Check current value. nextDateTime = nextDateTime + datetime.timedelta(hours=1) seqDS.appendWithDateTime(nextDateTime, 3) self.assertEqual(round(lsReg[-1], 2), 3) # Check future values. futureDateTime = nextDateTime + datetime.timedelta(hours=1) self.assertEqual(round(lsReg.getValueAt(futureDateTime), 2), 4) futureDateTime = futureDateTime + datetime.timedelta(minutes=30) self.assertEqual(round(lsReg.getValueAt(futureDateTime), 2), 4.5) futureDateTime = futureDateTime + datetime.timedelta(minutes=30) self.assertEqual(round(lsReg.getValueAt(futureDateTime), 2), 5) # Move forward in sub-second increments. nextDateTime = nextDateTime + datetime.timedelta(milliseconds=50) seqDS.appendWithDateTime(nextDateTime, 4) nextDateTime = nextDateTime + datetime.timedelta(milliseconds=50) seqDS.appendWithDateTime(nextDateTime, 5) self.assertEqual(round(lsReg[-1], 2), 5)
def datetime_aligned(ds1, ds2, maxLen=dataseries.DEFAULT_MAX_LEN): """ Returns two dataseries that exhibit only those values whose datetimes are in both dataseries. :param ds1: A DataSeries instance. :type ds1: :class:`DataSeries`. :param ds2: A DataSeries instance. :type ds2: :class:`DataSeries`. :param maxLen: The maximum number of values to hold for the returned :class:`DataSeries`. Once a bounded length is full, when new items are added, a corresponding number of items are discarded from the opposite end. :type maxLen: int. """ aligned1 = dataseries.SequenceDataSeries(maxLen) aligned2 = dataseries.SequenceDataSeries(maxLen) Syncer(ds1, ds2, aligned1, aligned2) return (aligned1, aligned2)
def testHighLow(self): values = dataseries.SequenceDataSeries() high = highlow.High(values, 5) low = highlow.Low(values, 3) for value in [1, 2, 3, 4, 5]: values.append(value) self.assertEqual(high[-1], 5) self.assertEqual(low[-1], 3)
def testEmpty(self): ds = dataseries.SequenceDataSeries([]) self.assertTrue(ds.getFirstValidPos() == 0) self.assertTrue(ds.getLength() == 0) self.assertTrue(ds.getValue() == None) self.assertTrue(ds.getValue(1) == None) self.assertTrue(ds.getValueAbsolute(0) == None) self.assertTrue(ds.getValueAbsolute(1) == None)
def testBounded(self): ds = dataseries.SequenceDataSeries(maxLen=2) for i in xrange(100): ds.append(i) if i > 0: self.assertEqual(ds[0], i - 1) self.assertEqual(ds[1], i) self.assertEqual(len(ds), 2)
def testStdDev_1(self): values = [1, 1, 2, 3, 5] seqDS = dataseries.SequenceDataSeries() stdDev = stats.StdDev(seqDS, 1) for value in values: seqDS.append(value) for i in stdDev: self.assertEqual(i, 0)
def onBars(self, bars, instrument): try: values = self.__values[instrument] except KeyError: values = dataseries.SequenceDataSeries() self.__values[instrument] = values taValue = self.__calculator.calculate(self.__feed, instrument) values.appendWithDateTime(bars.getDateTime(), taValue)
def testStdDev_Bounded(self): values = [1, 1, 2, 3, 5] seqDS = dataseries.SequenceDataSeries() stdDev = stats.StdDev(seqDS, 2, maxLen=2) for value in values: seqDS.append(value) self.assertEqual(stdDev[0], numpy.array([2, 3]).std()) self.assertEqual(stdDev[1], numpy.array([3, 5]).std())
def test_from_csv(testcase, filename, filterClassBuilder, roundDecimals=2, maxLen=dataseries.DEFAULT_MAX_LEN): inputValues, expectedValues = load_test_csv(get_data_file_path(filename)) inputDS = dataseries.SequenceDataSeries(maxLen=maxLen) filterDS = filterClassBuilder(inputDS) for i in xrange(len(inputValues)): inputDS.append(inputValues[i]) value = safe_round(filterDS[i], roundDecimals) expectedValue = safe_round(expectedValues[i], roundDecimals) testcase.assertEqual(value, expectedValue)
def __buildSlope(self, values, period, slopeMaxLen=dataseries.DEFAULT_MAX_LEN): seqDS = dataseries.SequenceDataSeries() ret = trend.Slope(seqDS, period, slopeMaxLen) for value in values: seqDS.append(value) return ret
def testFullyAligned(self): size = 20 ds1 = dataseries.SequenceDataSeries() ds2 = dataseries.SequenceDataSeries() ads1, ads2 = aligned.datetime_aligned(ds1, ds2) now = datetime.datetime.now() for i in xrange(size): ds1.appendWithDateTime(now + datetime.timedelta(seconds=i), i) ds2.appendWithDateTime(now + datetime.timedelta(seconds=i), i) self.assertEqual(len(ds1), len(ds2)) for ads in [ads1, ads2]: self.assertEqual(len(ads), size) for i in xrange(size): self.assertEqual(ads.getValueAbsolute(i), i) self.assertEqual(ads.getDateTimes()[i], now + datetime.timedelta(seconds=i))
def testNotAligned(self): size = 20 ds1 = dataseries.SequenceDataSeries() ds2 = dataseries.SequenceDataSeries() ads1, ads2 = aligned.datetime_aligned(ds1, ds2) now = datetime.datetime.now() for i in range(size): if i % 2 == 0: ds1.appendWithDateTime(now + datetime.timedelta(seconds=i), i) else: ds2.appendWithDateTime(now + datetime.timedelta(seconds=i), i) self.assertEqual(len(ds1), len(ds2)) for ads in [ads1, ads2]: self.assertEqual(len(ads), 0) self.assertEqual(ads.getValueAbsolute(0), None) self.assertEqual(ads.getDateTimes(), [])
def __init__(self, dataSeries, fastEMA, slowEMA, signalEMA, maxLen=None): assert(fastEMA > 0) assert(slowEMA > 0) assert(fastEMA < slowEMA) assert(signalEMA > 0) super(MACD, self).__init__(maxLen) # We need to skip some values when calculating the fast EMA in order for both EMA # to calculate their first values at the same time. # I'M FORCING THIS BEHAVIOUR ONLY TO MAKE THIS FITLER MATCH TA-Lib MACD VALUES. self.__fastEMASkip = slowEMA - fastEMA self.__fastEMAWindow = ma.EMAEventWindow(fastEMA) self.__slowEMAWindow = ma.EMAEventWindow(slowEMA) self.__signalEMAWindow = ma.EMAEventWindow(signalEMA) self.__signal = dataseries.SequenceDataSeries(maxLen) self.__histogram = dataseries.SequenceDataSeries(maxLen) dataSeries.getNewValueEvent().subscribe(self.__onNewValue)
def __buildWMA(self, weights, values, seqMaxLen=dataseries.DEFAULT_MAX_LEN, wmaMaxLen=dataseries.DEFAULT_MAX_LEN): seqDS = dataseries.SequenceDataSeries(maxLen=seqMaxLen) ret = ma.WMA(seqDS, weights, wmaMaxLen) for value in values: seqDS.append(value) return ret
def __init__(self, feed, instrument, ema1_period, ema2_period, ema3_period): super(AS001Strategy, self).__init__(feed, Broker(100000, feed, commission=TradePercentage(0.00075))) self.__instrument = instrument self.__ema1_period = ema1_period self.__ema2_period = ema2_period self.__ema3_period = ema3_period self.__hlc3 = dataseries.SequenceDataSeries() self.__position = None
def testEventWindow(self): ds = dataseries.SequenceDataSeries() smaEW = ma.SMAEventWindow(10) sma = ma.SMA(ds, 10) smaEW.onNewValue(None, None) # This value should get skipped for i in xrange(100): ds.append(i) smaEW.onNewValue(None, i) self.assertEqual(sma[-1], smaEW.getValue()) smaEW.onNewValue(None, None) # This value should get skipped
def testEmpty(self): ds = dataseries.SequenceDataSeries() self.assertTrue(len(ds) == 0) with self.assertRaises(IndexError): ds[-1] with self.assertRaises(IndexError): ds[-2] with self.assertRaises(IndexError): ds[0] with self.assertRaises(IndexError): ds[1]
def testUnderlyingDataSeries(self): ds = dataseries.SequenceDataSeries() testFilter = TestFilter(ds) for i in range(10): ds.append(i) ds.append(None) self.assertEqual(testFilter.getDataSeries(), ds) for i in range(0, len(testFilter)): self.assertEqual(testFilter[i], ds[i]) self.assertEqual(testFilter.getDataSeries()[i], ds[i])
def testZScore(self): values = [1.10, 2.20, 4.00, 5.10, 6.00, 7.10, 8.20, 9.00, 10.10, 3.00, 4.10, 5.20, 7.00, 8.10, 9.20, 16.00, 17.10, 18.20, 19.30, 20.40] expected = [None, None, None, None, 1.283041407, 1.317884611, 1.440611043, 1.355748299, 1.4123457, -1.831763202, -0.990484842, -0.388358578, 0.449889908, 1.408195169, 1.332948099, 1.867732104, 1.334258333, 1.063608066, 0.939656572, 1.414213562] seqDS = dataseries.SequenceDataSeries() zscore = stats.ZScore(seqDS, 5) i = 0 for value in values: seqDS.append(value) if i >= 4: self.assertEqual(round(zscore[-1], 4), round(expected[i], 4)) i += 1
def __buildTrend(self, values, trendDays, positiveThreshold, negativeThreshold, trendMaxLen=None): seqDS = dataseries.SequenceDataSeries() ret = linreg.Trend(seqDS, trendDays, positiveThreshold, negativeThreshold, trendMaxLen) for value in values: seqDS.append(value) return ret