Initial checkin

--HG--
branch : sandbox
This commit is contained in:
Andreas
2009-06-24 19:11:31 +00:00
parent e554144922
commit 773d4dfe6c
17 changed files with 2313 additions and 0 deletions

449
mpl/fibionacci.py Normal file
View File

@@ -0,0 +1,449 @@
# Copyright (c) 2008 Andreas Balogh
# See LICENSE for details.
""" animated drawing of ticks
using self.canvas embedded in Tk application
Fibionacci retracements of 61.8, 50.0, 38.2, 23.6 % of min and max
"""
# system imports
import datetime
import os
import re
import logging
import sys
import warnings
import Tkinter as Tk
import numpy as np
import matplotlib
matplotlib.use('TkAgg')
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
from matplotlib.dates import date2num
# local imports
# constants
ONE_MINUTE = 60. / 86400.
LOW, NONE, HIGH = range(-1, 2)
# globals
LOG = logging.getLogger()
logging.basicConfig(level=logging.DEBUG,
format='%(asctime)s.%(msecs)03i %(levelname).4s %(process)d:%(thread)d %(message)s',
datefmt='%H:%M:%S')
MDF_REO = re.compile("(..):(..):(..)\.*(\d+)*")
def tdl(tick_date):
""" returns a list of tick tuples (cdt, last) for specified day """
fiid = "846900"
year = tick_date.strftime("%Y")
yyyymmdd = tick_date.strftime("%Y%m%d")
filename = "%s.csv" % (fiid)
filepath = os.path.join("d:\\rttrd-prd-var\\consors-mdf\\data", year, yyyymmdd, filename)
x = [ ]
y = [ ]
fh = open(filepath, "r")
try:
prev_last = ""
for line in fh:
flds = line.split(",")
# determine file version
if flds[2] == "LAST":
last = float(flds[3])
vol = float(flds[4])
else:
last = float(flds[4])
vol = 0.0
# skip ticks with same last price
if prev_last == last:
continue
else:
prev_last = last
# parse time
mobj = MDF_REO.match(flds[0])
if mobj is None:
raise ValueError("no match for [%s]" % (flds[0],))
(hh, mm, ss, ms) = mobj.groups()
if ms:
c_time = datetime.time(int(hh), int(mm), int(ss), int(ms) * 1000)
else:
c_time = datetime.time(int(hh), int(mm), int(ss))
cdt = datetime.datetime.combine(tick_date, c_time)
x.append(date2num(cdt))
y.append(last)
finally:
fh.close()
# throw away first line of file (close price from previous day)
del x[0]
del y[0]
return (x, y)
class Lohi:
"""Time series online low and high detector."""
def __init__(self, bias):
assert(bias > 0)
self.bias = bias
self.low0 = None
self.high0 = None
self.prev_lohi = NONE
self.lohis = [ ]
self.lows = [ ]
self.highs = [ ]
def __call__(self, tick):
"""Add extended tick to the max min parser.
@param tick: The value of the current tick.
@type tick: tuple(cdt, last)
@return: 1. Tick if new max min has been detected,
2. None otherwise.
"""
n, cdt, last = tick
res = None
# automatic initialisation
if self.low0 is None:
self.low0 = tick
self.lows.append((n, cdt, last - 1))
if self.high0 is None:
self.high0 = tick
self.highs.append((n, cdt, last + 1))
if last > self.high0[2]:
self.high0 = tick
if self.prev_lohi == NONE:
if self.high0[2] > self.low0[2] + self.bias:
res = self.high0
self.low0 = self.high0
self.lows.append(self.high0)
self.lohis.append(self.high0)
self.prev_lohi = HIGH
if last < self.low0[2]:
self.low0 = tick
if self.prev_lohi == NONE:
if self.low0[2] < self.high0[2] - self.bias:
res = self.low0
self.high0 = self.low0
self.lows.append(self.low0)
self.lohis.append(self.low0)
self.prev_lohi = LOW
if self.high0[1] < cdt - ONE_MINUTE and \
((self.prev_lohi == LOW and \
self.high0[2] > self.lows[-1][2] + self.bias) or
(self.prev_lohi == HIGH and \
self.high0[2] > self.highs[-1][2])):
res = self.high0
self.low0 = self.high0
self.highs.append(self.high0)
self.lohis.append(self.high0)
self.prev_lohi = HIGH
if self.low0[1] < cdt - ONE_MINUTE and \
((self.prev_lohi == LOW and \
self.low0[2] < self.lows[-1][2]) or
(self.prev_lohi == HIGH and \
self.low0[2] < self.highs[-1][2] - self.bias)):
res = self.low0
self.high0 = self.low0
self.lows.append(self.low0)
self.lohis.append(self.low0)
self.prev_lohi = LOW
if res:
return (self.prev_lohi, res)
else:
return None
class Acp:
"""Always correct predictor"""
def __init__(self, lows, highs):
self.lows = lows
self.highs = highs
def __call__(self, tick):
"""Always correct predictor.
Requires previous run of DelayedAcp to determine lows and highs.
@param tick: The value of the current tick.
@type tick: tuple(n, cdt, last)
@return: 1. Tick if new max min has been detected,
2. None otherwise.
"""
n, cdt, last = tick
res = None
return res
def find_lows_highs(xs, ys):
dacp = DelayedAcp(10)
for tick in zip(range(len(xs)), xs, ys):
dacp(tick)
return dacp.lows, dacp.highs
class DelayedAcp:
"""Time series max & min detector."""
def __init__(self, bias):
assert(bias > 0)
self.bias = bias
self.trend = None
self.mm0 = None
self.lohis = [ ]
self.lows = [ ]
self.highs = [ ]
def __call__(self, tick):
"""Add extended tick to the max min parser.
@param tick: The value of the current tick.
@type tick: tuple(n, cdt, last)
@return: 1. Tick if new max min has been detected,
2. None otherwise.
"""
n, cdt, last = tick
res = None
# automatic initialisation
if self.mm0 is None:
# initalise water mark
self.mm0 = tick
res = self.mm0
self.lows = [(n, cdt, last - 1)]
self.highs = [(n, cdt, last + 1)]
else:
# initalise trend until price has changed
if self.trend is None or self.trend == 0:
self.trend = cmp(last, self.mm0[2])
# check for max
if self.trend > 0:
if last > self.mm0[2]:
self.mm0 = tick
if last < self.mm0[2] - self.bias:
self.lohis.append(self.mm0)
self.highs.append(self.mm0)
res = self.mm0
# revert trend & water mark
self.mm0 = tick
self.trend = -1
# check for min
if self.trend < 0:
if last < self.mm0[2]:
self.mm0 = tick
if last > self.mm0[2] + self.bias:
self.lohis.append(self.mm0)
self.lows.append(self.mm0)
res = self.mm0
# revert trend & water mark
self.mm0 = tick
self.trend = +1
return (cmp(self.trend, 0), res)
class Main:
def __init__(self):
warnings.simplefilter("default", np.RankWarning)
self.ylow = None
self.yhigh = None
self.advance_count = 1
self.root = Tk.Tk()
self.root.wm_title("Embedding in TK")
# create plot
fig = plt.figure()
self.ax1 = fig.add_subplot(211) # ticks
self.ax2 = fig.add_subplot(212) # diff from polyfit
# ax3 = fig.add_subplot(313) # cash
self.ax1.set_ylabel("ticks")
self.ax2.set_ylabel("polyfit diff")
# ax3.set_ylabel("cash")
major_fmt = mdates.DateFormatter('%H:%M:%S')
self.ax1.xaxis.set_major_formatter(major_fmt)
self.ax1.format_xdata = major_fmt
self.ax1.format_ydata = lambda x: '%1.2f' % x
self.ax1.grid(True)
self.ax2.xaxis.set_major_formatter(major_fmt)
self.ax2.format_xdata = major_fmt
self.ax2.format_ydata = lambda x: '%1.2f' % x
self.ax2.grid(True)
# rotates and right aligns the x labels, and moves the bottom of the
# axes up to make room for them
fig.autofmt_xdate()
# create artists
LOG.debug("Loading ticks...")
self.x, self.y = tdl(datetime.datetime(2009, 6, 3))
LOG.debug("Ticks loaded.")
lows, highs = find_lows_highs(self.x, self.y)
self.mmh = Lohi(10)
self.w0 = 0
self.wd = 1000
self.low_high_crs = 0
xr, yr = self.tick_window(self.w0, self.wd)
fit = np.average(yr)
self.tl, = self.ax1.plot_date(xr, yr, '-')
self.fl, = self.ax1.plot_date(xr, (fit,) * len(xr), 'k--')
self.mh, = self.ax1.plot_date(xr, (yr[0],) * len(xr), 'g:')
self.ml, = self.ax1.plot_date(xr, (yr[0],) * len(xr), 'r:')
self.him, = self.ax1.plot_date([x for n, x, y in lows], [y for n, x, y in lows], 'go')
self.lom, = self.ax1.plot_date([x for n, x, y in highs], [y for n, x, y in highs], 'ro')
self.dl, = self.ax2.plot_date(xr, (0,) * len(xr), '-')
self.set_axis(xr, yr)
# embed canvas in Tk
self.canvas = FigureCanvasTkAgg(fig, master=self.root)
self.canvas.draw()
self.canvas.get_tk_widget().pack(side=Tk.TOP, fill=Tk.BOTH, expand=Tk.TRUE)
# toolbar = NavigationToolbar2TkAgg( self.canvas, self.root )
# toolbar.update()
# self.canvas._tkself.canvas.pack(side=Tk.TOP, fill=Tk.BOTH, expand=1)
fr1 = Tk.Frame(master=self.root)
bu1 = Tk.Button(master=fr1, text='Quit', command=self.root.quit)
bu2 = Tk.Button(master=fr1, text='Stop', command=self.stop)
bu3 = Tk.Button(master=fr1, text='Resume', command=self.resume)
bu4 = Tk.Button(master=fr1, text='1x', command=self.times_one)
bu5 = Tk.Button(master=fr1, text='5x', command=self.times_five)
bu6 = Tk.Button(master=fr1, text='10x', command=self.times_ten)
bu1.pack(side=Tk.RIGHT, padx=5, pady=5)
bu6.pack(side=Tk.RIGHT, padx=5, pady=5)
bu5.pack(side=Tk.RIGHT, padx=5, pady=5)
bu4.pack(side=Tk.RIGHT, padx=5, pady=5)
bu2.pack(side=Tk.RIGHT, padx=5, pady=5)
bu3.pack(side=Tk.RIGHT, padx=5, pady=5)
fr1.pack(side=Tk.BOTTOM)
def animate(self):
self.w0 += self.advance_count
# prepare timeline window
xr, yr = self.tick_window(self.w0, self.wd)
while self.low_high_crs < self.w0 + self.wd:
self.mark_low_high(self.low_high_crs)
self.low_high_crs += 1
# build polynomial fit
mms = self.mmh.lohis
if len(mms) > 1:
mx = [ (x - int(x)) * 86400 for x in xr ]
my = yr
polyval = np.polyfit(mx, my, 10)
fit = np.polyval(polyval, mx)
self.fl.set_data(xr, fit)
# calc diff
self.dl.set_data(xr, yr - fit)
maxs = self.mmh.highs
if len(maxs) > 1:
n, x1, y1 = maxs[-2]
n, x2, y2 = maxs[-1]
x3 = xr[-1]
polyfit = np.polyfit((x1, x2), (y1, y2), 1)
y3 = np.polyval(polyfit, x3)
self.mh.set_data((x1, x2, x3), (y1, y2, y3))
mins = self.mmh.lows
if len(mins) > 1:
n, x1, y1 = mins[-2]
n, x2, y2 = mins[-1]
x3 = xr[-1]
polyfit = np.polyfit((x1, x2), (y1, y2), 1)
y3 = np.polyval(polyfit, x3)
self.ml.set_data((x1, x2, x3), (y1, y2, y3))
# update tick line
self.tl.set_data(xr, yr)
# update axis
self.set_axis(xr, yr)
self.canvas.draw()
if self.w0 < len(self.x) - self.wd - 1:
self.after_id = self.root.after(10, self.animate)
def set_axis(self, xr, yr, bias=50):
if self.ylow is None:
self.ylow = yr[0] - bias / 2
self.yhigh = yr[0] + bias / 2
for y in yr:
if y < self.ylow:
self.ylow = y
self.yhigh = self.ylow + bias
if y > self.yhigh:
self.yhigh = y
self.ylow = self.yhigh - bias
self.ax1.axis([xr[0], xr[-1], self.ylow, self.yhigh])
self.ax2.axis([xr[0], xr[-1], -25, +25])
def tick_window(self, w0, wd=1000):
return (self.x[w0:w0 + wd], self.y[w0:w0 + wd])
def mark_low_high(self, n):
x = self.x
y = self.y
rc = self.mmh((n, x[n], y[n]))
if rc:
lohi, tick = rc
nlh, xlh, ylh = tick
if lohi < 0:
# low
self.ax1.annotate('low',
xy=(x[nlh], y[nlh]),
xytext=(x[n], y[nlh]),
arrowprops=dict(facecolor='red',
frac=0.3,
shrink=0.1))
elif lohi > 0:
# high
self.ax1.annotate('high',
xy=(x[nlh], y[nlh]),
xytext=(x[n], y[nlh]),
arrowprops=dict(facecolor='green',
frac=0.3,
shrink=0.1))
def stop(self):
if self.after_id:
self.root.after_cancel(self.after_id)
self.after_id = None
def resume(self):
if self.after_id is None:
self.after_id = self.root.after(10, self.animate)
def times_one(self):
self.advance_count = 1
def times_five(self):
self.advance_count = 5
def times_ten(self):
self.advance_count = 10
def run(self):
self.root.after(500, self.animate)
self.root.mainloop()
self.root.destroy()
if __name__ == "__main__":
app = Main()
app.run()

444
mpl/fibionacci2.py Normal file
View File

@@ -0,0 +1,444 @@
# Copyright (c) 2008 Andreas Balogh
# See LICENSE for details.
""" animated drawing of ticks
using self.canvas embedded in Tk application
Fibionacci retracements of 61.8, 50.0, 38.2, 23.6 % of min and max
"""
# system imports
import datetime
import os
import re
import logging
import warnings
import math
import Tkinter as Tk
import numpy as np
import matplotlib
matplotlib.use('TkAgg')
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
from matplotlib.dates import date2num
# local imports
# constants
ONE_MINUTE = 60. / 86400.
LOW, NONE, HIGH = range(-1, 2)
# globals
LOG = logging.getLogger()
logging.basicConfig(level=logging.DEBUG,
format='%(asctime)s.%(msecs)03i %(levelname).4s %(process)d:%(thread)d %(message)s',
datefmt='%H:%M:%S')
MDF_REO = re.compile("(..):(..):(..)\.*(\d+)*")
def tdl(tick_date):
""" returns a list of tick tuples (cdt, last) for specified day """
fiid = "846900"
year = tick_date.strftime("%Y")
yyyymmdd = tick_date.strftime("%Y%m%d")
filename = "%s.csv" % (fiid)
filepath = os.path.join("c:\\rttrd-prd-var\\consors-mdf\\data", year, yyyymmdd, filename)
x = [ ]
y = [ ]
fh = open(filepath, "r")
try:
prev_last = ""
for line in fh:
flds = line.split(",")
# determine file version
if flds[2] == "LAST":
last = float(flds[3])
vol = float(flds[4])
else:
last = float(flds[4])
vol = 0.0
# skip ticks with same last price
if prev_last == last:
continue
else:
prev_last = last
# parse time
mobj = MDF_REO.match(flds[0])
if mobj is None:
raise ValueError("no match for [%s]" % (flds[0],))
(hh, mm, ss, ms) = mobj.groups()
if ms:
c_time = datetime.time(int(hh), int(mm), int(ss), int(ms) * 1000)
else:
c_time = datetime.time(int(hh), int(mm), int(ss))
cdt = datetime.datetime.combine(tick_date, c_time)
x.append(date2num(cdt))
y.append(last)
finally:
fh.close()
# throw away first line of file (close price from previous day)
del x[0]
del y[0]
return (x, y)
def num2sod(x):
frac, integ = math.modf(x)
return frac * 86400
class Lohi:
"""Time series online low and high detector."""
def __init__(self, bias):
assert(bias > 0)
self.bias = bias
self.low0 = None
self.high0 = None
self.prev_lohi = NONE
self.lohis = [ ]
self.lows = [ ]
self.highs = [ ]
def __call__(self, tick):
"""Add extended tick to the max min parser.
@param tick: The value of the current tick.
@type tick: tuple(cdt, last)
@return: 1. Tick if new max min has been detected,
2. None otherwise.
"""
n, cdt, last = tick
res = None
# automatic initialisation
if self.low0 is None:
self.low0 = tick
self.lows.append((n, cdt, last - 1))
if self.high0 is None:
self.high0 = tick
self.highs.append((n, cdt, last + 1))
if last > self.high0[2]:
self.high0 = tick
if self.prev_lohi == NONE:
if self.high0[2] > self.low0[2] + self.bias:
res = self.high0
self.low0 = self.high0
self.lows.append(self.high0)
self.lohis.append(self.high0)
self.prev_lohi = HIGH
if last < self.low0[2]:
self.low0 = tick
if self.prev_lohi == NONE:
if self.low0[2] < self.high0[2] - self.bias:
res = self.low0
self.high0 = self.low0
self.lows.append(self.low0)
self.lohis.append(self.low0)
self.prev_lohi = LOW
if self.high0[1] < cdt - ONE_MINUTE and \
((self.prev_lohi == LOW and \
self.high0[2] > self.lows[-1][2] + self.bias) or
(self.prev_lohi == HIGH and \
self.high0[2] > self.highs[-1][2])):
res = self.high0
self.low0 = self.high0
self.highs.append(self.high0)
self.lohis.append(self.high0)
self.prev_lohi = HIGH
if self.low0[1] < cdt - ONE_MINUTE and \
((self.prev_lohi == LOW and \
self.low0[2] < self.lows[-1][2]) or
(self.prev_lohi == HIGH and \
self.low0[2] < self.highs[-1][2] - self.bias)):
res = self.low0
self.high0 = self.low0
self.lows.append(self.low0)
self.lohis.append(self.low0)
self.prev_lohi = LOW
if res:
return (self.prev_lohi, res)
else:
return None
class Acp:
"""Always correct predictor"""
def __init__(self, lows, highs):
self.lows = lows
self.highs = highs
def __call__(self, tick):
"""Always correct predictor.
Requires previous run of DelayedAcp to determine lows and highs.
@param tick: The value of the current tick.
@type tick: tuple(n, cdt, last)
@return: 1. Tick if new max min has been detected,
2. None otherwise.
"""
n, cdt, last = tick
res = None
return res
def find_lows_highs(xs, ys):
dacp = DelayedAcp(10)
for tick in zip(range(len(xs)), xs, ys):
dacp(tick)
return dacp.lows, dacp.highs
class DelayedAcp:
"""Time series max & min detector."""
def __init__(self, bias):
assert(bias > 0)
self.bias = bias
self.trend = None
self.mm0 = None
self.lohis = [ ]
self.lows = [ ]
self.highs = [ ]
def __call__(self, tick):
"""Add extended tick to the max min parser.
@param tick: The value of the current tick.
@type tick: tuple(n, cdt, last)
@return: 1. Tick if new max min has been detected,
2. None otherwise.
"""
n, cdt, last = tick
res = None
# automatic initialisation
if self.mm0 is None:
# initalise water mark
self.mm0 = tick
res = self.mm0
self.lows = [(n, cdt, last - 1)]
self.highs = [(n, cdt, last + 1)]
else:
# initalise trend until price has changed
if self.trend is None or self.trend == 0:
self.trend = cmp(last, self.mm0[2])
# check for max
if self.trend > 0:
if last > self.mm0[2]:
self.mm0 = tick
if last < self.mm0[2] - self.bias:
self.lohis.append(self.mm0)
self.highs.append(self.mm0)
res = self.mm0
# revert trend & water mark
self.mm0 = tick
self.trend = -1
# check for min
if self.trend < 0:
if last < self.mm0[2]:
self.mm0 = tick
if last > self.mm0[2] + self.bias:
self.lohis.append(self.mm0)
self.lows.append(self.mm0)
res = self.mm0
# revert trend & water mark
self.mm0 = tick
self.trend = +1
return (cmp(self.trend, 0), res)
class Main:
def __init__(self):
warnings.simplefilter("default", np.RankWarning)
self.ylow = None
self.yhigh = None
self.advance_count = 1
self.root = Tk.Tk()
self.root.wm_title("Embedding in TK")
# create plot
fig = plt.figure()
self.ax1 = fig.add_subplot(211) # ticks
self.ax2 = fig.add_subplot(212) # diff from polyfit
# ax3 = fig.add_subplot(313) # cash
self.ax1.set_ylabel("ticks")
self.ax2.set_ylabel("polyfit diff")
# ax3.set_ylabel("cash")
major_fmt = mdates.DateFormatter('%H:%M:%S')
self.ax1.xaxis.set_major_formatter(major_fmt)
self.ax1.format_xdata = major_fmt
self.ax1.format_ydata = lambda x: '%1.2f' % x
self.ax1.grid(True)
self.ax2.xaxis.set_major_formatter(major_fmt)
self.ax2.format_xdata = major_fmt
self.ax2.format_ydata = lambda x: '%1.2f' % x
self.ax2.grid(True)
# rotates and right aligns the x labels, and moves the bottom of the
# axes up to make room for them
fig.autofmt_xdate()
# create artists
LOG.debug("Loading ticks...")
self.x, self.y = tdl(datetime.datetime(2009, 6, 3))
LOG.debug("Ticks loaded.")
lows, highs = find_lows_highs(self.x, self.y)
self.mmh = Lohi(10)
self.w0 = 0
self.wd = 1000
self.low_high_crs = 0
xr, yr = self.tick_window(self.w0, self.wd)
fit = np.average(yr)
self.tl, = self.ax1.plot_date(xr, yr, '-')
self.fl, = self.ax1.plot_date(xr, (fit,) * len(xr), 'k--')
self.mh, = self.ax1.plot_date(xr, (yr[0],) * len(xr), 'g:')
self.ml, = self.ax1.plot_date(xr, (yr[0],) * len(xr), 'r:')
self.him, = self.ax1.plot_date([x for n, x, y in lows], [y for n, x, y in lows], 'go')
self.lom, = self.ax1.plot_date([x for n, x, y in highs], [y for n, x, y in highs], 'ro')
self.dl, = self.ax2.plot_date(xr, (0,) * len(xr), '-')
self.set_axis(xr, yr)
# embed canvas in Tk
self.canvas = FigureCanvasTkAgg(fig, master=self.root)
self.canvas.draw()
self.canvas.get_tk_widget().pack(side=Tk.TOP, fill=Tk.BOTH, expand=Tk.TRUE)
# toolbar = NavigationToolbar2TkAgg( self.canvas, self.root )
# toolbar.update()
# self.canvas._tkself.canvas.pack(side=Tk.TOP, fill=Tk.BOTH, expand=1)
fr1 = Tk.Frame(master=self.root)
bu1 = Tk.Button(master=fr1, text='Quit', command=self.root.quit)
bu2 = Tk.Button(master=fr1, text='Stop', command=self.stop)
bu3 = Tk.Button(master=fr1, text='Resume', command=self.resume)
bu4 = Tk.Button(master=fr1, text='1x', command=self.times_one)
bu5 = Tk.Button(master=fr1, text='5x', command=self.times_five)
bu6 = Tk.Button(master=fr1, text='10x', command=self.times_ten)
bu1.pack(side=Tk.RIGHT, padx=5, pady=5)
bu6.pack(side=Tk.RIGHT, padx=5, pady=5)
bu5.pack(side=Tk.RIGHT, padx=5, pady=5)
bu4.pack(side=Tk.RIGHT, padx=5, pady=5)
bu2.pack(side=Tk.RIGHT, padx=5, pady=5)
bu3.pack(side=Tk.RIGHT, padx=5, pady=5)
fr1.pack(side=Tk.BOTTOM)
def animate(self):
self.w0 += self.advance_count
# prepare timeline window
xr, yr = self.tick_window(self.w0, self.wd)
while self.low_high_crs < self.w0 + self.wd:
self.mark_low_high(self.low_high_crs)
self.low_high_crs += 1
# build polynomial fit
mms = self.mmh.lohis
if len(mms) > 1:
mx = [ num2sod(x) for x in xr ]
my = yr
polyval = np.polyfit(mx, my, 10)
fit = np.polyval(polyval, mx)
self.fl.set_data(xr, fit)
# calc diff
self.dl.set_data(xr, yr - fit)
highs = self.mmh.highs
if len(highs) >= 4:
coefs = np.polyfit([num2sod(x) for n, x, y in highs[-4:]], [y for n, x, y in highs[-4:]], 3)
self.mh.set_data(xr, [np.polyval(coefs, num2sod(x)) for x in xr])
lows = self.mmh.lows
if len(lows) >= 4:
coefs = np.polyfit([num2sod(x) for n, x, y in lows[-4:]], [y for n, x, y in lows[-4:]], 3)
self.ml.set_data(xr, [np.polyval(coefs, num2sod(x)) for x in xr])
# update tick line
self.tl.set_data(xr, yr)
# update axis
self.set_axis(xr, yr)
self.canvas.draw()
if self.w0 < len(self.x) - self.wd - 1:
self.after_id = self.root.after(10, self.animate)
def set_axis(self, xr, yr, bias=50):
if self.ylow is None:
self.ylow = yr[0] - bias / 2
self.yhigh = yr[0] + bias / 2
for y in yr:
if y < self.ylow:
self.ylow = y
self.yhigh = self.ylow + bias
if y > self.yhigh:
self.yhigh = y
self.ylow = self.yhigh - bias
self.ax1.axis([xr[0], xr[-1], self.ylow, self.yhigh])
self.ax2.axis([xr[0], xr[-1], -25, +25])
def tick_window(self, w0, wd = 1000):
return (self.x[w0:w0 + wd], self.y[w0:w0 + wd])
def mark_low_high(self, n):
x = self.x
y = self.y
rc = self.mmh((n, x[n], y[n]))
if rc:
lohi, tick = rc
nlh, xlh, ylh = tick
if lohi < 0:
# low
self.ax1.annotate('low',
xy=(x[nlh], y[nlh]),
xytext=(x[n], y[nlh]),
arrowprops=dict(facecolor='red',
frac=0.3,
shrink=0.1))
elif lohi > 0:
# high
self.ax1.annotate('high',
xy=(x[nlh], y[nlh]),
xytext=(x[n], y[nlh]),
arrowprops=dict(facecolor='green',
frac=0.3,
shrink=0.1))
def stop(self):
if self.after_id:
self.root.after_cancel(self.after_id)
self.after_id = None
def resume(self):
if self.after_id is None:
self.after_id = self.root.after(10, self.animate)
def times_one(self):
self.advance_count = 1
def times_five(self):
self.advance_count = 5
def times_ten(self):
self.advance_count = 10
def run(self):
self.root.after(500, self.animate)
self.root.mainloop()
self.root.destroy()
if __name__ == "__main__":
app = Main()
app.run()

174
mpl/mpl-blit.py Normal file
View File

@@ -0,0 +1,174 @@
# Copyright (c) 2009 Andreas Balogh
# See LICENSE for details.
""" animated drawing of ticks
using blit method
"""
# system imports
import Tkinter as tk
import datetime
import os
import re
import logging
import sys
import matplotlib.pyplot as plt
from matplotlib.dates import date2num
import matplotlib.dates as mdates
import numpy as np
# local imports
# constants
# globals
LOG = logging.getLogger()
logging.basicConfig(level=logging.DEBUG,
format='%(asctime)s.%(msecs)03i %(levelname).4s %(process)d:%(thread)d %(message)s',
datefmt='%H:%M:%S')
MDF_REO = re.compile("(..):(..):(..)\.*(\d+)*")
def tdl(tick_date):
""" returns a list of tick tuples (cdt, last) for specified day """
fiid = "846900"
year = tick_date.strftime("%Y")
yyyymmdd = tick_date.strftime("%Y%m%d")
filename = "%s.csv" % (fiid)
filepath = os.path.join("d:\\rttrd-prd-var\\consors-mdf\\data", year, yyyymmdd, filename)
x = [ ]
y = [ ]
fh = open(filepath, "r")
try:
prev_last = ""
for line in fh:
flds = line.split(",")
# determine file version
if flds[2] == "LAST":
last = float(flds[3])
vol = float(flds[4])
else:
last = float(flds[4])
vol = 0.0
# skip ticks with same last price
if prev_last == last:
continue
else:
prev_last = last
# parse time
mobj = MDF_REO.match(flds[0])
if mobj is None:
raise ValueError("no match for [%s]" % (flds[0],))
(hh, mm, ss, ms) = mobj.groups()
if ms:
c_time = datetime.time(int(hh), int(mm), int(ss), int(ms) * 1000)
else:
c_time = datetime.time(int(hh), int(mm), int(ss))
cdt = datetime.datetime.combine(tick_date, c_time)
x.append(date2num(cdt))
y.append(last)
finally:
fh.close()
# throw away first line of file (close price from previous day)
del x[0]
del y[0]
return (x, y)
def main():
LOG.debug("Loading ticks...")
x, y = tdl(datetime.datetime(2009,6,3))
LOG.debug("Ticks loaded.")
fig = plt.figure()
ax1 = fig.add_subplot(311) # ticks
canvas = ax1.figure.canvas
# ax2 = fig.add_subplot(312) # gearing
# ax3 = fig.add_subplot(313) # cash
ax1.set_ylabel("ticks")
# ax2.set_ylabel("gearing")
# ax3.set_ylabel("cash")
xr = [x[0]] * 500
yr = [y[0]] * 500
line, = ax1.plot_date(xr, yr, '-', xdate = True)
major_fmt = mdates.DateFormatter('%H:%M:%S')
ax1.xaxis.set_major_formatter(major_fmt)
# ax1.axis('tight')
# format the coords message box
def price(x): return '%1.2f'%x
# ax.format_xdata = mdates.DateFormatter('%Y-%m-%d')
ax1.format_xdata = mdates.DateFormatter('%H:%M:%S')
ax1.format_ydata = price
ax1.grid(True)
# rotates and right aligns the x labels, and moves the bottom of the
# axes up to make room for them
fig.autofmt_xdate()
background = canvas.copy_from_bbox(ax1.bbox)
def animate():
w = 1000
bias = 10
ymin = min(y[0:100])
ymax = max(y[0:100])
low = ymin - bias
high = ymax + bias
trend = 0
for i in range(0, len(x)-w):
# restore the clean slate background
canvas.restore_region(background)
# prepare timeline window
xr = x[i:i+w]
yr = y[i:i+w]
# update line
line.set_xdata(xr)
line.set_ydata(yr)
# determine y axis
if yr[-1] > ymax:
ymax = yr[-1]
if ymax - 50 < min(yr):
ymin = ymax - 50
if yr[-1] < ymin:
ymin = yr[-1]
if ymin + 50 > max(yr):
ymax = ymin + 50
ax1.axis([xr[0], xr[-1], ymin, ymax])
# check low high and annotate
if i > 0 and i % 150 == 0:
ax1.annotate('low/high',
xy = (xr[-10], yr[-10]),
xytext = (xr[-5], yr[-10] + 10),
arrowprops = dict(facecolor = 'black',
frac = 0.2,
headwidth = 10,
linewidth = 0.1,
shrink = 0.05))
# just draw the animated artist
# FIXME: redraw all items in graph
ax1.draw_artist(line)
# just redraw the axes rectangle
canvas.blit(ax1.bbox)
root = fig.canvas.manager.window
root.after(100, animate)
plt.show()
if __name__ == "__main__":
main()

163
mpl/mpl-draw.py Normal file
View File

@@ -0,0 +1,163 @@
# Copyright (c) 2008 Andreas Balogh
# See LICENSE for details.
""" animated drawing of ticks
using draw method
"""
# system imports
import Tkinter as tk
import datetime
import os
import re
import logging
import sys
import matplotlib.pyplot as plt
from matplotlib.dates import date2num
import matplotlib.dates as mdates
import numpy as np
# local imports
# constants
# globals
LOG = logging.getLogger()
logging.basicConfig(level=logging.DEBUG,
format='%(asctime)s.%(msecs)03i %(levelname).4s %(process)d:%(thread)d %(message)s',
datefmt='%H:%M:%S')
MDF_REO = re.compile("(..):(..):(..)\.*(\d+)*")
def tdl(tick_date):
""" returns a list of tick tuples (cdt, last) for specified day """
fiid = "846900"
year = tick_date.strftime("%Y")
yyyymmdd = tick_date.strftime("%Y%m%d")
filename = "%s.csv" % (fiid)
filepath = os.path.join("d:\\rttrd-prd-var\\consors-mdf\\data", year, yyyymmdd, filename)
x = [ ]
y = [ ]
fh = open(filepath, "r")
try:
prev_last = ""
for line in fh:
flds = line.split(",")
# determine file version
if flds[2] == "LAST":
last = float(flds[3])
vol = float(flds[4])
else:
last = float(flds[4])
vol = 0.0
# skip ticks with same last price
if prev_last == last:
continue
else:
prev_last = last
# parse time
mobj = MDF_REO.match(flds[0])
if mobj is None:
raise ValueError("no match for [%s]" % (flds[0],))
(hh, mm, ss, ms) = mobj.groups()
if ms:
c_time = datetime.time(int(hh), int(mm), int(ss), int(ms) * 1000)
else:
c_time = datetime.time(int(hh), int(mm), int(ss))
cdt = datetime.datetime.combine(tick_date, c_time)
x.append(date2num(cdt))
y.append(last)
finally:
fh.close()
# throw away first line of file (close price from previous day)
del x[0]
del y[0]
return (x, y)
def main():
LOG.debug("Loading ticks...")
x, y = tdl(datetime.datetime(2009,6,3))
LOG.debug("Ticks loaded.")
fig = plt.figure()
ax1 = fig.add_subplot(311) # ticks
# ax2 = fig.add_subplot(312) # gearing
# ax3 = fig.add_subplot(313) # cash
ax1.set_ylabel("ticks")
# ax2.set_ylabel("gearing")
# ax3.set_ylabel("cash")
xr = [x[0]] * 500
yr = [y[0]] * 500
line, = ax1.plot_date(xr, yr, '-', xdate = True)
major_fmt = mdates.DateFormatter('%H:%M:%S')
ax1.xaxis.set_major_formatter(major_fmt)
# ax1.axis('tight')
# format the coords message box
def price(x): return '%1.2f'%x
# ax.format_xdata = mdates.DateFormatter('%Y-%m-%d')
ax1.format_xdata = mdates.DateFormatter('%H:%M:%S')
ax1.format_ydata = price
ax1.grid(True)
# rotates and right aligns the x labels, and moves the bottom of the
# axes up to make room for them
fig.autofmt_xdate()
def animate():
w = 1000
bias = 10
ymin = min(y[0:100])
ymax = max(y[0:100])
low = ymin - bias
high = ymax + bias
trend = 0
for i in range(0, len(x)-w):
# prepare timeline window
xr = x[i:i+w]
yr = y[i:i+w]
# update line
line.set_xdata(xr)
line.set_ydata(yr)
# determine y axis
if yr[-1] > ymax:
ymax = yr[-1]
if ymax - 50 < min(yr):
ymin = ymax - 50
if yr[-1] < ymin:
ymin = yr[-1]
if ymin + 50 > max(yr):
ymax = ymin + 50
ax1.axis([xr[0], xr[-1], ymin, ymax])
# check low high and annotate
if i > 0 and i % 150 == 0:
ax1.annotate('low/high',
xy = (xr[-10], yr[-10]),
xytext = (xr[-5], yr[-10] + 10),
arrowprops = dict(facecolor = 'black',
frac = 0.2,
headwidth = 10,
linewidth = 0.1,
shrink = 0.05))
fig.canvas.draw()
root = fig.canvas.manager.window
root.after(100, animate)
plt.show()
if __name__ == "__main__":
main()

330
mpl/mpl-embedded.py Normal file
View File

@@ -0,0 +1,330 @@
# Copyright (c) 2008 Andreas Balogh
# See LICENSE for details.
""" animated drawing of ticks
using self.canvas embedded in Tk application
Fibionacci retracements of 61.8, 50.0, 38.2, 23.6 % of min and max
"""
# system imports
import datetime
import os
import re
import logging
import sys
import warnings
import Tkinter as Tk
import numpy as np
import matplotlib
matplotlib.use('TkAgg')
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
from matplotlib.figure import Figure
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
from matplotlib.dates import date2num
# local imports
# constants
# globals
LOG = logging.getLogger()
logging.basicConfig(level=logging.DEBUG,
format='%(asctime)s.%(msecs)03i %(levelname).4s %(process)d:%(thread)d %(message)s',
datefmt='%H:%M:%S')
MDF_REO = re.compile("(..):(..):(..)\.*(\d+)*")
def tdl(tick_date):
""" returns a list of tick tuples (cdt, last) for specified day """
fiid = "846900"
year = tick_date.strftime("%Y")
yyyymmdd = tick_date.strftime("%Y%m%d")
filename = "%s.csv" % (fiid)
filepath = os.path.join("d:\\rttrd-prd-var\\consors-mdf\\data", year, yyyymmdd, filename)
x = [ ]
y = [ ]
fh = open(filepath, "r")
try:
prev_last = ""
for line in fh:
flds = line.split(",")
# determine file version
if flds[2] == "LAST":
last = float(flds[3])
vol = float(flds[4])
else:
last = float(flds[4])
vol = 0.0
# skip ticks with same last price
if prev_last == last:
continue
else:
prev_last = last
# parse time
mobj = MDF_REO.match(flds[0])
if mobj is None:
raise ValueError("no match for [%s]" % (flds[0],))
(hh, mm, ss, ms) = mobj.groups()
if ms:
c_time = datetime.time(int(hh), int(mm), int(ss), int(ms) * 1000)
else:
c_time = datetime.time(int(hh), int(mm), int(ss))
cdt = datetime.datetime.combine(tick_date, c_time)
x.append(date2num(cdt))
y.append(last)
finally:
fh.close()
# throw away first line of file (close price from previous day)
del x[0]
del y[0]
return (x, y)
class Mmh:
"""Time series max & min detector."""
def __init__(self, bias):
assert(bias > 0)
self.bias = bias
self.trend = None
self.mm0 = None
self.mms = [ ]
self.mins = [ ]
self.maxs = [ ]
def __call__(self, tick):
"""Add extended tick to the max min parser.
@param tick: The value of the current tick.
@type tick: tuple(cdt, last)
@return: 1. Tick if new max min has been detected,
2. None otherwise.
"""
n, cdt, last = tick
res = None
# automatic initialisation
if self.mm0 is None:
# initalise water mark
self.mm0 = tick
res = self.mm0
self.mins = [(n, cdt, last - 1)]
self.maxs = [(n, cdt, last + 1)]
else:
# initalise trend until price has changed
if self.trend is None or self.trend == 0:
self.trend = cmp(last, self.mm0[2])
# check for max
if self.trend > 0:
if last > self.mm0[2]:
self.mm0 = tick
if last < self.mm0[2] - self.bias:
self.mms.insert(0, self.mm0)
self.maxs.append(self.mm0)
res = self.mm0
# revert trend & water mark
self.mm0 = tick
self.trend = -1
# check for min
if self.trend < 0:
if last < self.mm0[2]:
self.mm0 = tick
if last > self.mm0[2] + self.bias:
self.mms.insert(0, self.mm0)
self.mins.append(self.mm0)
res = self.mm0
# revert trend & water mark
self.mm0 = tick
self.trend = +1
return res
class Main:
def __init__(self):
LOG.debug("Loading ticks...")
self.x, self.y = tdl(datetime.datetime(2009,6,3))
LOG.debug("Ticks loaded.")
self.mmh = Mmh(10)
self.root = Tk.Tk()
self.root.wm_title("Embedding in TK")
fig = plt.figure()
self.ax1 = fig.add_subplot(111) # ticks
# ax2 = fig.add_subplot(312) # gearing
# ax3 = fig.add_subplot(313) # cash
self.ax1.set_ylabel("ticks")
# ax2.set_ylabel("gearing")
# ax3.set_ylabel("cash")
self.w = 1000
self.bias = 10
xr = self.x[0:self.w]
yr = self.y[0:self.w]
fit = np.average(yr)
self.tl, = self.ax1.plot_date(xr, yr, '-')
self.fl, = self.ax1.plot_date(xr, (fit, ) * self.w, 'k--')
self.mh, = self.ax1.plot_date(xr, (yr[0], ) * self.w, 'g:')
self.ml, = self.ax1.plot_date(xr, (yr[0], ) * self.w, 'r:')
major_fmt = mdates.DateFormatter('%H:%M:%S')
self.ax1.xaxis.set_major_formatter(major_fmt)
self.ax1.format_xdata = mdates.DateFormatter('%H:%M:%S')
self.ax1.format_ydata = lambda x: '%1.2f'%x
self.ax1.grid(True)
# rotates and right aligns the x labels, and moves the bottom of the
# axes up to make room for them
fig.autofmt_xdate()
self.ax1.axis([xr[0], xr[-1]+180./86400., min(yr), max(yr)])
self.canvas = FigureCanvasTkAgg(fig, master=self.root)
self.canvas.draw()
self.canvas.get_tk_widget().pack(side=Tk.TOP, fill=Tk.BOTH, expand=1)
# toolbar = NavigationToolbar2TkAgg( self.canvas, self.root )
# toolbar.update()
# self.canvas._tkself.canvas.pack(side=Tk.TOP, fill=Tk.BOTH, expand=1)
fr1 = Tk.Frame(master = self.root)
bu1 = Tk.Button(master = fr1, text='Quit', command=self.root.quit)
bu2 = Tk.Button(master = fr1, text='Stop', command=self.stop)
bu3 = Tk.Button(master = fr1, text='Resume', command=self.resume)
bu1.pack(side = Tk.RIGHT, padx = 5, pady = 5)
bu2.pack(side = Tk.RIGHT, padx = 5, pady = 5)
bu3.pack(side = Tk.RIGHT, padx = 5, pady = 5)
fr1.pack(side = Tk.BOTTOM)
def animate_start(self):
warnings.simplefilter("default", np.RankWarning)
self.ymin = min(self.y[0:self.w])
self.ymax = max(self.y[0:self.w])
self.low = self.ymin - self.bias
self.high = self.ymax + self.bias
self.trend = 0
self.i = 0
for n in range(0, self.w):
self.mark_low_high(n)
self.root.after(500, self.animate_step)
def animate_step(self):
# prepare timeline window
xr = np.array( self.x[self.i:self.i+self.w] )
yr = np.array( self.y[self.i:self.i+self.w] )
# update line
self.tl.set_xdata(xr)
self.tl.set_ydata(yr)
# determine y axis
if yr[-1] > self.ymax:
self.ymax = yr[-1]
if self.ymax - 50 < min(yr):
self.ymin = self.ymax - 50
if yr[-1] < self.ymin:
self.ymin = yr[-1]
if self.ymin + 50 > max(yr):
self.ymax = self.ymin + 50
# check self.low self.high and annotate
fwd = 2
for n in range(self.i+self.w, self.i+self.w+fwd):
self.mark_low_high(n)
self.i += fwd
# build polynomial fit
mms = self.mmh.mms
if len(mms) > 1:
# mx = [ (x - int(x)) * 86400 for n, x, y in mms[:4] ]
# my = [ y for n, x, y in mms[:4] ]
mx = [ (x - int(x)) * 86400 for x in xr ]
my = yr
xre = [ xr[-1] + x/86400. for x in range(1, 181)]
xr2 = np.append(xr, xre)
# print "mx: ", mx
# print "my: ", my
polyval = np.polyfit(mx, my, 30)
# print "poly1d: ", polyval
intx = np.array(xr, dtype = int)
sodx = xr - intx
sodx *= 86400
s2x = np.append(sodx, range(sodx[-1], sodx[-1]+180))
fit = np.polyval(polyval, s2x)
self.fl.set_xdata(xr2)
self.fl.set_ydata(fit)
maxs = self.mmh.maxs
if len(maxs) > 1:
n, x1, y1 = maxs[-2]
n, x2, y2 = maxs[-1]
x3 = xr[-1]
polyfit = np.polyfit((x1, x2), (y1, y2), 1)
y3 = np.polyval(polyfit, x3)
self.mh.set_data((x1, x2, x3), (y1, y2, y3))
mins = self.mmh.mins
if len(mins) > 1:
n, x1, y1 = mins[-2]
n, x2, y2 = mins[-1]
x3 = xr[-1]
polyfit = np.polyfit((x1, x2), (y1, y2), 1)
y3 = np.polyval(polyfit, x3)
self.ml.set_data((x1, x2, x3), (y1, y2, y3))
# draw
self.ax1.axis([xr[0], xr[-1]+180./86400., self.ymin, self.ymax])
self.canvas.draw()
if self.i < len(self.x)-self.w-1:
self.after_id = self.root.after(10, self.animate_step)
def build_fit(self):
pass
def mark_low_high(self, n):
x = self.x
y = self.y
rc = self.mmh((n, x[n], y[n]))
if rc:
nlh, xlh, ylh = rc
if self.mmh.trend > 0:
# low
self.ax1.annotate('low',
xy = (x[nlh], y[nlh]),
xytext = (x[n], y[nlh]),
arrowprops = dict(facecolor = 'red',
shrink = 0.05))
# an.set_annotation_clip(True)
elif self.mmh.trend < 0:
# high
self.ax1.annotate('high',
xy = (x[nlh], y[nlh]),
xytext = (x[n], y[nlh]),
arrowprops = dict(facecolor = 'green',
shrink = 0.05))
# an.set_annotation_clip(True)
def stop(self):
if self.after_id:
self.root.after_cancel(self.after_id)
self.after_id = None
def resume(self):
if self.after_id is None:
self.after_id = self.root.after(10, self.animate_step)
def run(self):
self.root.after(500, self.animate_start)
self.root.mainloop()
self.root.destroy()
if __name__ == "__main__":
app = Main()
app.run()