Initial checkin
--HG-- branch : sandbox
This commit is contained in:
17
.project
Normal file
17
.project
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>sandbox</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.python.pydev.PyDevBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.python.pydev.pythonNature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
12
.pydevproject
Normal file
12
.pydevproject
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<?eclipse-pydev version="1.0"?>
|
||||
|
||||
<pydev_project>
|
||||
<pydev_pathproperty name="org.python.pydev.PROJECT_SOURCE_PATH">
|
||||
<path>/sandbox/src</path>
|
||||
<path>/sandbox/gui</path>
|
||||
<path>/sandbox/mpl</path>
|
||||
</pydev_pathproperty>
|
||||
<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.5</pydev_property>
|
||||
<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Default</pydev_property>
|
||||
</pydev_project>
|
||||
3
.settings/org.eclipse.ltk.core.refactoring.prefs
Normal file
3
.settings/org.eclipse.ltk.core.refactoring.prefs
Normal file
@@ -0,0 +1,3 @@
|
||||
#Mon Feb 11 22:12:56 CET 2008
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=false
|
||||
4
.settings/org.eclipse.mylyn.tasks.ui.prefs
Normal file
4
.settings/org.eclipse.mylyn.tasks.ui.prefs
Normal file
@@ -0,0 +1,4 @@
|
||||
#Mon Feb 11 22:12:56 CET 2008
|
||||
eclipse.preferences.version=1
|
||||
project.repository.kind=trac
|
||||
project.repository.url=http\://localhost\:8080/xmlrpc
|
||||
6
.settings/org.eclipse.wst.validation.prefs
Normal file
6
.settings/org.eclipse.wst.validation.prefs
Normal file
@@ -0,0 +1,6 @@
|
||||
#Mon Feb 11 22:12:56 CET 2008
|
||||
DELEGATES_PREFERENCE=delegateValidatorListorg.eclipse.wst.xsd.core.internal.validation.eclipse.XSDDelegatingValidator\=org.eclipse.wst.xsd.core.internal.validation.eclipse.Validator;
|
||||
USER_BUILD_PREFERENCE=enabledBuildValidatorListorg.eclipse.wst.xsd.core.internal.validation.eclipse.XSDDelegatingValidator;org.eclipse.wst.dtd.core.internal.validation.eclipse.Validator;org.eclipse.wst.xml.core.internal.validation.eclipse.Validator;
|
||||
USER_MANUAL_PREFERENCE=enabledManualValidatorListorg.eclipse.wst.xsd.core.internal.validation.eclipse.XSDDelegatingValidator;org.eclipse.wst.dtd.core.internal.validation.eclipse.Validator;org.eclipse.wst.xml.core.internal.validation.eclipse.Validator;
|
||||
USER_PREFERENCE=overrideGlobalPreferencesfalse
|
||||
eclipse.preferences.version=1
|
||||
365
gui/bottier.py
Normal file
365
gui/bottier.py
Normal file
@@ -0,0 +1,365 @@
|
||||
# Copyright (c) 2008 Andreas Balogh
|
||||
# See LICENSE for details.
|
||||
|
||||
""" decode ASCII greyscale """
|
||||
|
||||
# system imports
|
||||
|
||||
import Tkinter as Tk
|
||||
import logging
|
||||
from StringIO import StringIO
|
||||
from PIL import Image
|
||||
from PIL import ImageTk
|
||||
|
||||
# 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')
|
||||
|
||||
CODE = "#MWmBEKNQkAbqXHgUFRhdwp8&aDGVZ9utO03CYvlrI=i<7+?}(*[/|;!^-~`,:. "
|
||||
|
||||
def main():
|
||||
tkis = []
|
||||
# build gui
|
||||
root = Tk.Tk()
|
||||
root.title("bottier")
|
||||
bu1 = Tk.Button(root, text='Quit', command= root.quit)
|
||||
bu1.pack(side = Tk.BOTTOM, padx = 5, pady = 5)
|
||||
for s in (PIC1, PIC2, PIC3, PIC4, PIC5):
|
||||
im = ascii2img(s)
|
||||
tki = ImageTk.PhotoImage(im, gamma = 2)
|
||||
tkis.append(tki)
|
||||
la = Tk.Label(root, image = tki)
|
||||
la.pack(side = Tk.RIGHT, padx = 5, pady = 5)
|
||||
|
||||
root.mainloop()
|
||||
root.destroy()
|
||||
|
||||
def ascii2img(s):
|
||||
# create the image
|
||||
# lines = StringIO(s).readlines()
|
||||
# height = len(lines)
|
||||
# width = len(lines[0])
|
||||
# im = Image.new("L", (width, height))
|
||||
im = Image.new("L", (100, 100))
|
||||
for y, line in enumerate(StringIO(s)):
|
||||
for x, c in enumerate(line):
|
||||
im.putpixel((x, y), CODE.find(c) * 4)
|
||||
bbox = im.getbbox()
|
||||
bbim = im.crop(bbox)
|
||||
imx2 = bbim.resize((bbox[2]*2, bbox[3]*2), Image.ANTIALIAS)
|
||||
return imx2
|
||||
|
||||
PIC1 = """\
|
||||
BEmmmBBBBBNNEBBEEKBBHd&aDGapHNBEBBBBEKBEmBBEBBKgdp8wdRbEBKEEEEENKQNAAbbXUp8aD9
|
||||
BEBBBEKENNNEBEEKEEmAd8DZVG&RkEBmBBEEKBBBmmmmBBmbh&Da&wFQBmmmBmBmmmBWmmmBmmmBmm
|
||||
mBBBBBEKNKKKKKKENBkh8VVZGDwXNEBBBEEBBBBBmWmmmmmEgwaDGDpFKBBmmmmmmWmWWmWWWWWmmW
|
||||
EEBBKBEKNNKNEEEQEER&VZ99V8gNKBEBBEBEBBBmmmmmmmmWqh&DVGawqmEmBmmmmmBWmWWmWWMWWM
|
||||
KEBKEEKNKKKKKNNNBqG9OOtuGhAKEEEEBBBBBBBBBmmBBBmmEgwaDaa8RNBBBmBBBmmmmWWmWMWWWM
|
||||
BBBBENKQNKENNQNNmRu0003taXNKKEKEBEEBEBmmBBBmmBBmmNF8aDDawXKmWBBWBmmmMWWmWWWMMM
|
||||
EKEBKNkQNKNNNNQNBRO333YO&bQNKKKKBBBmWMWWMWWmmmBmmWAR8VGG&hbBmWWmmmWWWWMMMMMMMM
|
||||
NKEENAAkNKNkQNkKQ&3YYvvO&AKEEEBBmWWMMMMW#MMMMMMMMMWEgpGGDawbBBmBmBWmmWWWMWMWMM
|
||||
NKEKkAkkKNKkQQkKXZClrIv3DbNEWMMMMM#MMM#MM#MMM#MMMMMMmNgZZGVwEmBmmmWmmmmmWWWMM#
|
||||
QNQkkQQkNQQkkAkERtYr=Il3VHKWMMMMMMMMMM#M#MMWMMMMMMMMMEAdZVZREEmBBmmWmmmmmWWWMW
|
||||
kbkbAkQkNQQAkkQEpOv=i=rY9hBWWMWMMMMMMWMMBABmWMMWWWWMWWN899VdKEEBBmmmWmBBmmmWWW
|
||||
AbbbbkkkNQbbAQQNDCrii=Iv9dKmMMMMMMMMWWWmBXAKEmKghFQmMMBqVt9&QEEBBmBmmBBmmmmmmm
|
||||
bqqXXAkQNAqqXbQAG3I<<iIvOpEWMMMMWMMWWmEAAwdHXdpwdhRNWmBKp3tDqEEBKmEBmBmmmmBmBm
|
||||
qHgHHAbkkAXgHHAXZli7<i=l38EWWWMMMWmBAhhpwRdhRUgUgHHNmBQUCYOGUKEEBKBBBBBBBmmBBB
|
||||
XggUUXbkAqgUUUkguli7<<ir3DKmMWWWWBkggHggqXXbXXqHgbbbbAXGYGO9dQEEEEBmEBBmmBBmBm
|
||||
FhhRdFqqAqRRUFkFOr=<7<irCaNWmMWWmQqHbXggHFUddHgggHRgHFdOGaCt&ANNEmEBEmBBBBBmmB
|
||||
UUFddhgbqgRFFUAR0ri<++iICDkmmmmmKAbURRgFa8DpRdRwRRdqbqUUdYv0GbKKEEEKKBEBBBBBmm
|
||||
RFFdwpFXXUhdFUkhOIi77+<ICGQmmBKkUHHwgpR&hw8h&ahUqbqbg8Rd0lv3ZXKKKKKKKNKEEBEBBB
|
||||
hhdhwwRgUhhdhFbh3=<++7<il9kBWmEbXgRRGDut0tuDVDwaagbHARw0IIr3ugQNNNKEENNKEBEBBm
|
||||
8phhppwwdwwwhhqwYi7?+++7i0HEmBKbHhhZOO3v3u0O9VpDuaXUaOlIIIrCuUkNNQNKKKKEEBmEEB
|
||||
aDDa&8pwpppppdXdvi7++???<YaXAQKEKKgGtO3Y33Y0tZGDuDhdZCI=IIlCuUkNQNNNKEEBBBEEEE
|
||||
GVZVVVa&8w&&&8gwv<++?}}(+ICaHEEKEBNHwD900Cvvl0VaGwHwuv==I=IvtFkQkNQQNEEKKEEEBE
|
||||
ZZt99OuVVGGGGaRdvi?}???}}<iC8NBKEBBba&aDDVVGa&wFbEA&Ori===rvtUkkQNNNNEKEKEEEEE
|
||||
ttO0030uuu9ZZGahY<+?++?}}?+I0hKEmBENFVOrl3t&wRNBEKFD0IiiiIrvtgAkQNNNNNKEEEEEEE
|
||||
3033YYY3C333OuVF3<}}+++}?}}7rOHBEEKkHaCiiI0DwkBmBBbVv=i===rvtgAkQQQQKNENKKKEKK
|
||||
YYYvvrvvvlvrrrthZ<(?7+?+}?}?+lDQKBEQhaY==ru&XEBBBKptlrIlrIrYZHAkkQkQNNNNNKKNNN
|
||||
Ylll===llr=I=Il9a=}(((((**[}?=OUkBBNUVli=twAKBBENUuvlrlvvrrCZXAkAkkkkQQQQNNKNN
|
||||
I=II<7+=r=i=i=It&=([////*[}?}7IZUAkHUUlrY9dqXQKAdpZlrrvvYlrYaqAAAAbQkQQNQQQNKK
|
||||
<77+}}}+7i7+77I0G7*/|;|||*?????ItG&wdGCCttDpRUh8030YI<rCCvl0RqqbbAbkkkkkkQNNNN
|
||||
+??((((?+??+???OO}/;!;!;|}<+?}?7rCvvvlCC3COOO0ClI=Ili+irYvYVHqbbAbbQQkQQQQNNQQ
|
||||
?(*[[/[*}}*(*(+Vr*/;!^^!*7<<?}?7<rvlrIrr=IllvvrIi=il=?<=rl3hXXHqbbbAAAAAkQkkQQ
|
||||
([/;///|*[*(*}=V<*/;;;|(i=i7?}}}?+<<<<7+<7iI=i===iIYv7+iIltUHXXXqqbbAAAkkQQQQN
|
||||
/;!^^!;^;!||[*r9?[|//*?II<7+?((???777+}(*(??++<<i=rvYI77rvZUHgHXXqXAAAkAkkkNNQ
|
||||
;|^~-------^!!79+*/[(<==<<??}*[[**}??+***}}?++<<i=rY0trirvGgHHXXHXqAbbkAkkkkNQ
|
||||
!-~~~`~~~```~~*t<(}}<rI=7?++}*|;|/[(+?*/[[(*}?+77i=C09uYlY&gXqXXXXqqbAkkkQNQNQ
|
||||
~`,`~,,`::.:,:^tI+?<rvY7+7=lr<|^!;;[?+*|[*[***}?+7i<ltVZ30hHXXXXXbbbAkkkkkQkQN
|
||||
,::::::..,:.::~CC<+<lr7}?rY3O9=!^!|[*(/||[//|[*(}?77r99Vu9RXXXXHXXbAAkkAQQNQNN
|
||||
:.......:,`:.:,=0i77rr+?OZ&&aGO(^;|[([|;|////|/[*}+i0ui++=38Z&hgHHqbbbkAkQQQQN
|
||||
....::..`,`,::`lOi+?7I=+3DD&Z8ZY///[[|!;!!;||||[[(+Y0=7++=p03Cu3Y0DUbAkkQNNQNk
|
||||
....::,.:. `.:,<tr+}(+=rC8a&GY+////|;!!!!!;|/|||[*}IY33CYa0YviI0u33gkkQQkQNNNN
|
||||
:.............:[Or<}}(}+=a37}(*[/|;!^!!;!;;/[[*(}+irrt8UgdD9ZutO00RAAkNkQNKKKK
|
||||
,:::.:.:::.:,``v9l<?((*[*((*[/[/|!;|;!!;|//*(+7<=rYODapFgUHbQqhG9FbAQQkKNNNNKK
|
||||
,`,`:::``,,~`-!Otl<?(*[///[/||||;!;||!||[((}?7ilY0t9uDRgggHHqqqqqbkkNkQQNNKKNN
|
||||
!``~,,,----`~~-Z9ri+([[/[[[//||;;!;;;!|!//*(}?7=IlvC9hHgHgXbqqqbbAkQNNNKKKKKKK
|
||||
/!!!!^^!|!;;!;*aVl<}*[[[**/|;;;!;;;|!;!//[(?++<iiIl0aFgggUHHbqqbAANkQNNNKEKEEK
|
||||
}([;;|/;[/|/[[+pZv<?}(([(*[|;!!;||!|;;;!||[*+7<iirC9RFggUHHHXbbbkkNNQQKNEEEKKE
|
||||
7?}**/*//|/[**?aGvi+?(*(**|;!;;!;/||;||;;/[*}+<IlY3GUgHHUHHqbbAkkkQkNNKKNKENEE
|
||||
77++??}***((}(7&Dv=7?(**|||||;;;;;!|/|||||/*(?irYCtpgggUgXbHXAAAQkNKNNNNNNKKEE
|
||||
I=<<i<<+++?+++<p&Oli+(*[[|||||/|;;;||||//**[*?irYOaFHHXHXXqXqAAkkQkQNKNNNEKEBE
|
||||
rIIIIIi<7<=<77<p&tCI<?}([[[|//////|||//[[((}}+7ICZdXHXXXqbbbAbAkANQQNNQQQKEKEB
|
||||
3ClrlI<<<r=<<7rh&tvri7?}***/**/[[[[**[(*((?+++iv9pUHXXqqbbbXAAAAkNQNQNNQNNKEKB
|
||||
0Yrlvi<=i=rrI=ZRG0vI=<+?}?(***[((?}?((}}++77<=vupFqbXqAAkkkkkAkAkQkkQkNKNNKKEm
|
||||
O0YCCIiIrvYY3VRau3r=i7+??}(***(*}?}}??+77<<=lCOGpUqbbbAbAAQQQkAkkkQQkNNNKNKKKE
|
||||
tu0CCYrlllCODFaV3vIi<7++?}?}***(?7?}}?}<7iIrY3uVadqAbAAAbAkNQNQQQkQQNQQQNNQKKE
|
||||
ZtO30YYY33OVU8ZuClI<7???}??((*(}<r=+++++<=rv30t9ZagqbAAAkkkkkQkQNNNKNNNNNKNNKK
|
||||
DutOttu99u9Uq89O3vr<<777??}}(*(?7i<+7?7<iIlvYC0OuGdbbAbAAAkQNNNKNQKNKNNNNKNKKE
|
||||
&DVV9GaDGDhBWmBkFVYIiii<77+?}((}}++++?7<=rYY00OOOZwAkQQAAkQNNKNNEEKNNKBKEEEEEE
|
||||
d&aa8&8&8hNBBEBWBBEKXp90vll=i<i<i<i<i==lvC0OtuZagEMMNNkQkkQNNNNEKEEKEEKBBEKEBE
|
||||
Rwppw&DDdAMWWWWBbAbXEkEEEEENbqHUhdd8wFFgqQNBBWWmmEBMBKNNQNNNNNKEKEKKEKBEBBBBmB
|
||||
URwwpw&pqmWmNBBNEKbFQUqbFQUXAgNAkEkgXKBEBEENENKQKKW#MEQNQQNNNNEKEEKEBBBBEmmBBm
|
||||
gRhdhRhqmQghqHQNBAKANHXkgkgHAhAHHQgQbqQqBkEKBNKQEBmmMMKNQQQNNKEKKEBBEBEBBBBmBm
|
||||
gFFFRdwFkXaZOtuwgAQBBAAQXBbbKXEAqQXKAQQABQBNEBBNBmWENAkQNNQNNKEEEBBBBBBmBmBBBB
|
||||
bgRRUhdFNUa9OYvlvpFbQWWmEQQKbXQEkkENbBmNEmEBmBWWkNkgawXNQQNNNKEENKBBEEBBmBmBmm
|
||||
AAqXggHqKRDu0CvvvlvpKmQNNQkAbbbkAkQkQkNKKKNNNNKWBqGZG8gQKNbkKKKKEEEEEBWmBBBBmm
|
||||
kkkAbAAKkwGt3YYlvYCdKNgDu9u99ttV99GVZG&D&&GVZ9ZkKGu99&RQNNNNNEEKKKEKEEBmmBBBBB
|
||||
QKQQQkQEgaVt0CvvY3DKkV9u9uVVVtuu9ZVGDDDaDGZ99ut8Bqtt9DwbQNKKEKKEKKEEEEBBBmBEmm
|
||||
NNENNQEAhGZOCvYvvtbN&u9VDa&DDVGGapp88p8p8&DZuO0tgK&ttV&gNNKNNKKEKKEKKBEBBBBBBB
|
||||
NKKQQKKg8Duu0YvY3FNhuZVGD&ppwdhRggUUFUFdp&GuO00OZNNVuVahANKNNKEEEKEEEEBEBEmBBB
|
||||
KKKKNBbR8GZt0YCCpNUttuZZG&hFHqbbbAAkqXgwaV99ttO0OwBXu9&wqNEKEKEEKKKKNKKEBEBEBB
|
||||
KEEKEEXRpaVuO33VNqu0tuZVDadHAQKNNNNKNXhpDZZutOO00uABpVGwgNEKEEEEEKEEKEEBBBmmmE
|
||||
NNEEWMBQFwaGuuaQku0t9ZVa&pRXEBmBWWBBQHRpDGuutOO000aEKaawqBEEEBBBEKKNKEKEEEEBmm
|
||||
bkEEWWWWWWBQUgNbaOOOuZGDawUbKKNKNEmEbghw&DV9ttt0OO9XEghNWWEEEBBBBEENNKEEEEBBBB
|
||||
AqkKmBmmmMmmmBmEbdGVGGG&8dgkNNQNNNEmAUhp&DGV99u9VV&HWWmmmWBEKBBEEKEKKEEEEEEBBB
|
||||
7IYuG8wUHXqAQNKKNNENqRwdhFHNNKKNNNKmKXgRw&&&a8hbEBmmEBBBBmmBBEBEKBEEKEEEEBBBEm
|
||||
"""
|
||||
|
||||
PIC2 = """\
|
||||
*[}7[/*7+//|[i[/[(i+il0uDahFHXqqbAkkNEKkkNEEBmBBBKQkQAAQKBBEBBBEBENEKEKEEBEBBB
|
||||
<<++??+?(}}?}??+i====Ii+([/[/|*(}??+7=ii=il3VdgbkkNQkQkkkkNNNNNQNKNNEQEmmEEEEm
|
||||
<<77+++++?}???+<i=IrlI<7}[/|;/(*}?++7<===rY0GRqAAQkQkkkkkQkQQNKKEEKKEKBBEBEEBB
|
||||
?+??++??????}?+7<=IrlrIi+([[[[[*}???+iIiIIvOaFXbkkkkNQkkkkkNQQQNKKNNNKKBEEEBmE
|
||||
}}?}}?}}}((}(?777iIrlvri7}*[/[/**[(?7<ii=rYt&UHbkAkkkkAAAkKkQQNNNKKNNNEKEEEEEB
|
||||
((((((}(}}??+++7<=rvlvlIi?(*[/*[**(??7==IrYt8gXbkbkkAAkkAAQAQNQQNNQQNNNKEEEEEm
|
||||
*(((***}}}???7<<i=IIvllrIi+}*[/*[(}+<<i=rv3ZpUXbAAAkkAbAkkQkQQQQkQNKKKNKKEEEBW
|
||||
[*****}}}???+++<==Irvvvvl=<7}((*((??+iiIrv0VwgqbAAAbAAbAAAkkkkkkQQQNKQNKBBEKKE
|
||||
*}}**(((}}(+77<<<=IllvCCYlIi+?((??+++i==Il0VwHqbkkkAbAAAkkbkkkAAkkkQKKNKNNKEBB
|
||||
/[**(}}}}?}++++7iIrrlv333CYli7?}(}++7<iirvOVwHbAAAbAkkkkkAkKQAAAkkkKKKKKKEEEBB
|
||||
[(****((}??????7iIrlY330OO03ri<?}??+7i==rvtDhXbqbkkAAkkkkNNQQQQQQQQQNQNEEEEEKE
|
||||
[(**[/[((*((??++<IrvvC3Otuut3lI<77+7<i==rYODhHqbAAAQQQQkkNNQNQkkQQQQKQQKKEBEEB
|
||||
*[**[[[***((}}}?7=rrYC00Ot99O0Y=<<<<ii=Ir3u&FHXbkQkQQQQQkQkNNQkkkkkQkKKKNKKKKE
|
||||
||[*[[**[[**}}??+<=llCC0Otuu9t0vlI=ii==rv0ZpUXbAkQNNNNNQkQQQQkkQQQQkKNKNNNNKKE
|
||||
[|//[**[*(*}}}?++?<IilvY3Ou9ZZO0Cvr===lvY3DdgbAAbNQKKNkkQQQNQQkkQNKQkQkQQNEKKN
|
||||
^!;||[*[[/[**(}}}++7<iIlCOu99ZVu0ClIIrrrvtaRXbbkQQNkQNNQkQNQkQkkQQQNQNNNKEKKEB
|
||||
-!^!!||;//[**(??}}??+<irY3O99ZaG9t3YrrlvCt&FqbbkkNQkNNNQkQQNQQkQQkQNNENEEBEEBW
|
||||
-^!^^!;;///[[*(((***??<Iv3u9ZVGDGu03CYYYOVdgqbkQkNNkNQkQNQNAQQQQNKKENEEKKKEEEB
|
||||
~--^!;!!|||;|/[**[*(}?7=l0u9VZD&DVuO3YY3tGRXbAQNQQNkQQkQKKQkQQQkQNNQNKKKEEBBmK
|
||||
`-~-^!!!!;;|/[[[***(*?+=v0tu9VGa&aZt03Y0t&hHbkkQQNNkNQQNNQkkAkAkNNNNNNEBBEBmBB
|
||||
-~~~~-^^!;!||[[[[[***(+ilOZZuuuZVV9utOOuVpFHbkQNQNQNNQQNQkQAAkQQQkQQQNKEEBEEBE
|
||||
,,`~~--^!^;!|||//[[*(}+ICuVuCr=rYC330Ou9VwhFHqAAQkkkkkkkQkAAbQQQQQNQNNNKEBEEEK
|
||||
,```~~-^^;!;;/////[*(+<ltVZOr7}((}+7<irC0ZaphUqqXHHHXbkAbbAQAkQQQkkQQQNEEEKKBB
|
||||
::`````---~^;|||[*(??<lOZZt3I7?*[////[}+i=Y09awdwaG&whFUgXXbkbAkQQQQkNNKKKEKEE
|
||||
^:,``~~~~~^^^;||[*(?<r3u9u0v<((*/||//[/*(?7IOD8Dt33C0t9Ga8phFFgXqqbAQNKKKKKKEE
|
||||
.. :,`-~^^-^;|||[(7rY0ut3v=}(*(/|////[/(}iO8d89YvvYvvYCC3OtZDaphUgHXkQNQQNKBE
|
||||
[:::,`~~``--^!;|[(7IC003Y=7?(*//|||/[*[*}itphdDYiI303vlvYCvCCYC3t9ZDwFUHXbkNKK
|
||||
,:.::,`~~`---!;|[}<l0CYvr<?}([[[/////*[}It&hpZCI=IC3Yrl39uO3lIii=IIrC3uVpFHANE
|
||||
..:::::`~-~-^!;|[*?ilvvvr=<7}(([[*****}70&p89Y=ilCllIiICtu990vI=<7<=<==YOGRAKK
|
||||
.,::::,`~~~--!;;/[(?iIvYvlrIII7?+}}}(?+Caw8ZC=iIvvI<++<=Iv0tttOYlI===irY3VFQKB
|
||||
.::,::,`~~----^!;[(7==IrlvvvCvvllrrlrvOD8a9Yi<=vvl=i+}}?+<rCCtttO03vIrv0GRAKEW
|
||||
`:,:,,```~-^^!!;[(+<++<=lYC303C03OtttuVDVu3Ii=lYvl=r=<7<i==rvCOu9Zu0333ZdqKEBB
|
||||
:,```~~~^-!^;;|[*}+<+??7=vCOZGDVGGGVVVZttOCvvC3CrlO9u033OOtO0Otu99ut309hbNKEBB
|
||||
,~------^!;;///*}?7<77+irYOZawwRFgHgFhp&aGZuuuO3COZVVZ999uuttOOOO0330ZdXQEBBBB
|
||||
^^!^!!!^!|*[[((}?+<<iirlYO9apwwhHANKKNQAAUFhp&GGt9Zu0YvvYvvrrrlrlCC0ZRqNEEEKEE
|
||||
!;;;||||/[*(?}+77i==rlY3tV8wwpdUHXbkQKNKKKEKQkbgRdp&Vt03YlII====IYOGFANEBBEEEm
|
||||
;;|/[[[**}(+++7i=rlvY0uVD8wp&wdFHqqXXbAAAAKBmmmmWBQbgRpaG9tC3YvvCOGdXQEBBmBEBm
|
||||
/**((}?}?++<<Irlv300uZD8p8aa&wUqXqqqbqbqqqbAQNKEmWMWmEKNbgUd&GZZZDhqQKEKKEBBmW
|
||||
/((???++<<IIrlY30t9Vapp&aaDGwhHbAbbqXqbbXbqbAkAQKKBBWWWMWMmEkHRhFHbQQEBmEKEBBW
|
||||
}}+7<<ii=rlYY3Otu9VGaDGVVGD8hgXbAAAbXqAqbqbkkAAQQQKBBBmmBBmEKkAbANNNEEEBBmWWWW
|
||||
((+77<==IvvCCC0OOttZutu9ZG&dRgqbAAAAbqbbqkkkkAkkQQNKEKKKKKKENNQNNKEEBmmBmmmWWB
|
||||
**}?+<<i=IllvYYYCCC333OuZDpFHqAAAqbAbbbbqAkkAAkQKKKEKNKEKKKNQQQNKEBBBWmmBBWWMW
|
||||
/*}}?+<ii==rrlvvYYvYv0OuG8hgXbbkAbAAAAbbAkkkkAANKKKNNKKKKKKKKKNNEBBmWWWmmWMM#W
|
||||
/[*((?777<===IrIIrrlC0tVadFHbbkAbqbAkkbAAkQkQNNKKQNKEKNKKKKKQNEEBmmmWWMWWMWWMM
|
||||
[***(}?++7<i====I=IvCOuV8RgqbkAkAAkkkAbAQkQNQNNQQQNNEKKEKKKEEEEBmWWmmWmWWBBWEM
|
||||
[[[***(}}}7<7<<i=IIv3tV&dUqbqAAAbbAkkAbAQQNNNNQQNNKKEEEKNKKKEBBBBBEBBmBmmWMMWN
|
||||
[[[**(}(}}+?7<i==IrY39awRHbbbbbAbAAAAAAAkQQQkkkQNKNKKKKNKNNEEEBBEEBBWmmmWMWmWW
|
||||
*[(*(}}(}?}?7<<i=rY3OZahUHXAAbAkAkkAAqbqqAAkkAAQQKKEKKNKKNKKEKEBBEKBWM#WmmmmWW
|
||||
**(**(((}???<<<iIrv0uVpRgXXqqqqbAAbAAAAqqbAAkkQQNNNQQQNEBEBEEEEEBEEBMWMWWWWmmM
|
||||
"""
|
||||
|
||||
PIC3 = """\
|
||||
MMM#MM##MWMD{8M##MM####MMMMMM###M##M###MMM########M####MM##MMMMMMMMMMM#MMMWWMM
|
||||
M#MMMMM#M@A=2WWMWWMMM##M#MMM#W##M######M##M#M##M##MM###MM##MMWMMMMMMW##M#MMMMM
|
||||
MM##MWMBiW%oWMUmWWW@NM##MMWymM############M#MM###MM#MM##M#MMMMMMMMMMMW#MMMMMMM
|
||||
WMMWqmWMMW=B#WiWM#B?8WMMWWXmWMM###M#####MMMM###MMMM#M#M##M#MMMMMMMMMWMMMMMWMMW
|
||||
WWWgDD8@&9%#MBD####WWmmWWLmMW#MWM#####MWM#M#M##MM##M#MM#MMM#M#MMM#MWWMMMMMMWMM
|
||||
mWWWWmQWWCWWMMM###MWWBWMWWmcvxFXmMMM#MMMMMM#MMMMM#M#MMM##M#MMMMMMMMMMMMMMMWWMM
|
||||
MMMMMWWW$@#MMMM##M#WMW@WmAWi)77z@MMMMM##MM###M####MM##MM#M##MMMMMMMMMMWWMMMMWW
|
||||
WWWWWWWMFWMMMMMM#MMMMMWWWWAB313QWMMMMMMMMM#MMM#####MMM#MMM#M#M#MMMMMMMWMMWMMBm
|
||||
MWmWWWWMmMMMMMMMMM#M#M#kWWWMW<&WMMM##M#MM#M##M#MM#MMMMMWMMM#MMMM#MMMMMWMMMMMWW
|
||||
WN,NMWWmW#WMWWMMMMMMMWWMM##MMW&@MMMMM#MMM#######MMM#M#M#M#MMMMFWMMMM#MWmMMMMWW
|
||||
MMMMMMMMWMMMMMMMM#MMYmMMMMmmWMMMMMWMMMMMMM###M#MMMMM#####MMMM#MMMMMMMM<3MMMWWW
|
||||
##MMMMMWWMMMMMWWWWWMMWMMMMMMWW##Xu3bmmWWWM#M#MMMMMMMMM##MMMM#M#MM#MMMMWMMMMMMM
|
||||
MMWMM#MMW#MMWMMWWWWWWWMMWWMMM##MME%D=3@mWWMMMMMMMMWWMMMMMMM#M#MMMMM#MMMMMMMMWM
|
||||
WMMMM#MMmWWmmMMWWWWWWAWMQWMMMMMMMM80/38NWWMMWMMMMMWmBWWM###MMMMMMMM#WMMWWWWMWM
|
||||
M#MMWMMMMm8WWWWWMMWWWmWWMMMMM#MMWWWm<D<?8mMMMWMWMMM@@@mMWM#M#MMMMMWYY#MMMWMmWW
|
||||
MMWWMWWWWm@mmmWWWWQWWMWWMWWMMMMMWW]))|'`)lmm@BWWWWmQXNm@QNmWMMM#MWMMMMMWMMMMWW
|
||||
MWWWMMMWMWmWmmmmmWWWMWM#WMMWMMMMMMW<^))-~'':::'`?ocv2%d$k$QmMMMMMMMMMWMMMMMWWW
|
||||
WWWMMMW#MMWmmmmWMMWWM#MMNU#MMMMMM#m?))|-':: '-^~-|7=Y9q8qkmWMMMWMMMMWWWMMMWMM
|
||||
WM#MMMMMMWWWMWWWMWWWWMWWWWMWMMMMMW8||)-' .^~..')|?lzL8UqNmWMMMMMMMMMMMMMMMW
|
||||
MMMMMMMMWWWWWWWWmmmOO988@@mNWmQbQW=)|"~:. '^:. :-)[iYOy&$kmWWMMMMMMMMMMMMMMM
|
||||
#MMMWMWWWmmmmBBQmN&qA8eD9QAmWk@Q$<__[|': ._,:::~_/1v02DU$mmWMMMMMMMMMWWMMWM
|
||||
WMMWWmWMWmWmmAREEby8&=3xqN@mMWMMN<|||-:... .:-)-;;"+<cj0L68bmmWMMMMMMWWBWWMWWW
|
||||
##MMMMMMWMW@NF&@mmRkejv8BmWMMWWmm@O<?~:::::,-^|)/"]<1vvj26&bmmWMMMMMM#MWMMMM#W
|
||||
MMMMMMM##MWm@gygNmAQ88&BM#MMMMMWWMMmv':.,~;|7|)||/"<ivY3xt&@mWM##MMM#MWMM#MMM#
|
||||
M#MM##M##M###MMMMMWM###M#MMMMMM##MMMD`.:~_)+=7||"{+<1vvjtu&@@mMMMM##MMMMMMMMMM
|
||||
M#M#######M##M####W###M#M##MM##M###MD:.::-_+7l/{[+<1olzY098N@mMMMMM#MMM#MMMM#M
|
||||
M##M##M##M##M#M#M#W#M#MMMM#MMM###MMM&)~':'^_/7?|?711llv3xL8@QWM#M#M#MMMMMMMMMM
|
||||
MM#####M##M####M##M##M###MMMM#####MM82+)-)_)/[=+{{<1==YC2L8N@WM#MMMMMMMMMMMMMM
|
||||
######MM#MM#MMM#MM######M##M#######MMQL3Ii==o=x7<++<<cYjtDX@EmWMM#M###M##MMMMM
|
||||
M######M#MMMM#MMM##MM############M##M9v+]oL8Dyg=7<<1=lx2eR@NmmWWWMMMMMM##MMM#M
|
||||
########MM##MMMM##M######MMMMMMM#MWBQci1+{7<<=xl<<1clj96&F@mm@BWWWWMM#MM#MMMMM
|
||||
MM#WM###MMM####MM######MMWBU&AMWb2=Yj/]Ll<+7<1vtIo=Yx3ey&8@NbFqNmmWWWMM#M##MMM
|
||||
#M##M#MMM#M##M#M#MMWk%3i<++{{iWW&l+8811%R2YlI=c9CYvlC0t6DdEF88UA@@mmWWWMMM#MMM
|
||||
#MM#M#MMM###MMWUY<7{[_;)__^_)|gWDvuMmMM#MQDxYYvx6Yvj026yDgN&&88dUg@BmWmWM#MM#M
|
||||
####M#MMM#MWu1/|;-~-~~,`-~-;^)yWACbBWWM&BW&u6DD8RYvv3u6yFA$66yD&88qX@EmWMMM#MM
|
||||
#MM#####M#B<);;`,:::,:,,',^-^;?WW9z+?2mMmmQ2e88C==ojO9&8R$&vj0O2%%&R$@EmWMMMMM
|
||||
#M#M###MMWi|~`,:,,~'~,,,`-`--);lWB=++2mMWEWF9jo1ilO9&gX88U2x00Oxt9D&FX@EmWWMMM
|
||||
M#MM##MMMm<|)););~~~',~--^___;){B9<7<l@MmWWLcllYx9%&88FbL03jzCj32t6&8gg@BWWMMM
|
||||
#MM#M####MdYc<7")_^;;_//[++77<i=e1<<=ygNNolYYxuy88gAkk89O2xxz3Yjj3Le%8Xb@mWMMW
|
||||
#M########MMmbDY<<7icY3xe88U8Fg@l]0ov8WMFYv29D8ddbQ@@R8Dyutt3zYvz3z2Dy8$@mWWMM
|
||||
#######M####MMWm@$QmWmNQkAUd8dXmxlk<9@@M#m8D&8A@E@N@BA8&9O3Yll1oYYx2eDFQ@mWM#M
|
||||
#########MMMMMMMMMWWmBNQ@N@mWM##MFd3DuzzoI111<<77+<<<=3%6l<7<<7iIz2%&&dANWM#MM
|
||||
M##MMM##MM##MMM#MMMM#MMM###M#MMN63lo<7<+?{"{[[+[{{[??+7<<iY<777<IYxLy8q@mW#M#M
|
||||
######M##MMWMM#MMMMMM##MMMW8xl=<7+[[||||"|///"[/+{??{++71<1oOzcIv3%D8$QBmMW#MM
|
||||
#M###M##MMWMM##MMMMMMMW@xv=7{"||)-);;)||[/""/+++<]]++<<7111cljjj0O%&XQNmMMM#MM
|
||||
#####MM##M####M#####Wt=]{|))-^));;||"[+{[?{++<<ic=1=ooIccvvYC92u9y88q@mWMM###M
|
||||
#MMM#######M#####MAc<[);^---;-_))||/"{?++<71icIllYvvvC332uL9%%D&8UXQNWM#####MM
|
||||
#M#M########M#MMg<+|)--`-;_))||)/{"[?+7]<iilcYjCCxe2D%e&D%8&8UFXb@mW##M######M
|
||||
######M#######MY7);':'`__|"{/[[//"{7771illYv0OtDu&6&8RgFXq$kQ@NmM####M####MMM#
|
||||
#M#M#MM#M#M#MMdl7|;)/"{{{/{]+?{7<<1=olYz03Cuy&&dRFqA$Q@@BBmmW###########M#M###
|
||||
#M#######MM###mLI=<<1<<<7i71<iilY3CO2y6Y888RbAQmBBmWWMM##########M###M######MM
|
||||
#MM############m6CYYYCCYYvCj2e&8$qQQ@BNmWmmWWWMM###########M####M##########M#M
|
||||
######M########MmF&D8XdFARF$QB@RgdgAkNmWmWMM#####M###M###M#MM#M#MM##M##M##M###
|
||||
###M###########M##MMWmmWmmB@kb@BmWWWM##########M##MM####MM###M####MM#M#####MMM
|
||||
#MMM#######M######M######M##M#M##M#####M###############M#M#MM#MM#M#M####M#MM#M
|
||||
MMM#M#M######M##M#MM#M#########MMMMM#M##########MM#M###M#M##MMMM#MMMWMWMMMMWMM
|
||||
"""
|
||||
|
||||
PIC4 = """\
|
||||
N@NEKEBmmmmmWmmmmmmmmmmWWmmmWWWWmWWmWWmWWWWWWWWWWWWWmBuWWWWWMMWWWWWMMMMWMWMMWM
|
||||
BEEmmBmmmBmmmmmmmmmmmWmmWmWWWWWWWWmWmWWWWWWWWWWWWWWWWGDWWMWWMMMWMWMWMMWMMMMMMM
|
||||
BBBBBmmmBmmmmmmmmWWWWWWmmWWmWWWWWWWWWWWWWWWWWWWWWWWWWv$WMWWWWMWWWWWWMWMMMMMMMM
|
||||
EEKBmmmmmmmmmWmmmmmWWWWWWWWWWmWWWWWWWWWWWWWWWWWWWWWWmoBMWMWWWWMMMMMMMMMMWMMMMM
|
||||
EKmBmmmmmmmmmmmmWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWUYmWWMWWWMWMMMMWMMMMMMMMMM
|
||||
NEEBmmmmmmmWmmmmmmWWWWWWWWWWWWWWWWWWWWWmWWWWWWWWWWMWuTWWMMMWMMWMMWMMMMMMMMMMMM
|
||||
EEBmBmmmmmmmmmmBmmWWWWWWWWWWWWWWWWWWWWE5Ugx8bWWWWWWWxqWWMMMMMMMMMMMMMMMMMMMMMM
|
||||
KEmBmmmmmWmmmWmmmmmWmWWWWWWWWWWWWmBWWqc=~|&AY<&mWWWWbmMMMMMMMMMMMMMMMMMMMM#MMM
|
||||
NmEBBmmmmmmmWWmWmWWWWWWWWWWWWWWWmthb24x,_?)--`'xmWMWWMWMMMWMMMMMMMMM#M#MMMMMMM
|
||||
NEEBBmmmmmmmWmmWmWmWWWWWWWWWWWWmz8$o{_```'...::<mWWWMMWMMMMMMMMMMMMMMMMM#MMMMM
|
||||
EEEEEmmmmmmWmmWWKmWWWWWWWWWWWWW@~,vv),::. ::<@WWMWWWMMMMMMMMMMMMMMMM#####MMM
|
||||
BE@EBmmmmmmmWWWWmEWWWWWWmWmWWWWN<'D8v<+)-',|<=hWWWWWWWMMMMMMMM#MMMM#MM#MMM#MMM
|
||||
EBEEmEmmmWmWWWWWmbWWWWWWWWWWWBmB?7Fl[)|);~,,-?kWWWmWWWMWMMMMMMMMMMMM######MMMM
|
||||
@NEEBmBmWmmmmmmWW8mWWWWWWmWWWWWV)RL|'-_;`.:<&lbmWWWmWWWMMWWMMMMMMM#MMMMM##MM#M
|
||||
8@EmmmmmmWmmWWWmm&mWWWWWWWWWWWB):Ut<+17?-:|o@WWWMWWWWWMMMMMMMM#M#MMMM###M##M##
|
||||
u8NEBmmmmmWWWmmmWmWWWWWWWWWWmm<..nlvaOi{{ovv08mWWWWWMWWMMMMMM#MM########M#M##M
|
||||
t&KBBmmmmWWWWWWWWmmWWWWWWWBLL<:..88QA2l&$e2t2J==qWWWWWMMMMM#MMMMM##M###M#M####
|
||||
xD@mmmmmmmWWmWWWWWBWWWWA"1uY1/):-$mEA&BWEU@E@&TYlleKWWWWMMMMMM#MM#M#####M#####
|
||||
J8EmmmmmmmWWWWWWWWmWWWK^:.'=8&8GuUWWmmQgBWWWME&l7|-;"v@WMMMM#M#M##M###M#M###MM
|
||||
vSKmmmmWWWWWWWWWWWWWWWX: .|=7AW&A8mWkXAmWMMMM@0+)':'`-<mWMMMMMMM#M###MM######
|
||||
04bmmmmWWWWmWWWWWWWWWWW8^.<LooT@mWWWWmXG&@WMMMN5</~~'''`vBWWWMMM#M#########M##
|
||||
uj8BmmWmWWWWWWWWWWWmWMWQ.:Lg=<D58@WWWmFt3vx8NmmQ&j<{);~~?1IlkWWMMMM#M#####MMM#
|
||||
Sj%NmmWWWWWWWWWWWWWmWWWo :Jge32xG@MMWKhuxv<+[?=TgQA&C<||o<[|lI8mMM##M#######MM
|
||||
&JxABmWWWWWWWWWWWWWmWMW< .<g@qYI3QWWmQ8S0v=+|~'-^3Em@8xd8t1<<+|7YmMM##M#######
|
||||
&jJ&mmWWWWWWWWWWWMMWWWWe..=mWmo)<QWWNd%2jv<{_^`~~|UWWmmmEbqxl<?)|"jmMM##M###M#
|
||||
8OCnNWWmWWWWWWWMWMMMWMWQ.:8MMW2~|QWN8uYzlo+/^~,:~~^LMMMWWmqb8aTl]{"1m#########
|
||||
8&23$mmWWmWWWMWWWWMMMMWl<YWWMMg,)gW@V3=<??|;-`~`,-|8WMMMMMWWmmbDjo<<&###M#####
|
||||
8&308mWWWWWWWWWMMMWMMMWD5XWMMMm/_JAmA3<|;~`,~-;~;|?UMMMMMWWMWWmb&nOGW###M#####
|
||||
URLCSNWWWWWWMMWWMMWMMMMMRlmMMMWe+4NWmgY+");__/|||[{eWMWWWmWWmmNQbkWM#######M##
|
||||
bdn3TbWWWWWWWMMWWWMMMMMMMWe&WMMRYuKWMWgTzI==1<+{/[<io8WWmWWWWWmWM#############
|
||||
AF&O48mWWWWWMWWMMMMWMMMMMMW<LBWQ2gWMMMm@X%2Oz=7++71ilio&ENq8YDEM####M#########
|
||||
QmBB@EmWWWWWMMMMMMMMMMMMM##WD$WWU8W#MmX&nLVe2zc<1lc<77<<lXX00bhllN############
|
||||
d888e28&@mF&NWWMWMMMMMMMMM###WBNmEWMMWmQFgbR&5303zc<+++<11l&&t4CoB############
|
||||
8&S0C03Qmm@qXbKWMMMMMMMMMM#M##M#WWWMMMWWWWmm@AbqU%2v<<1<1<<1ogWWMM#M##########
|
||||
$X&G8bAX88gAbbKBmMMMMMMMWMMMMMM#MMX5mWMMMMMMMMWm@UaLxxCl=<]++<NMM#M#########MM
|
||||
g8&GaGnVD&nxux&UEWMMMMMMMMWMMMM##MA{i&@28@mmWWWmXt0x020xJYo1iouW#M############
|
||||
QS0zzYJ0G8%t25&ABmW#MMMMM#MM#M#MMM8""13TEWmWm@Ov3O2Cv===IlvvJvY@M############M
|
||||
E&23jjY3TV%0tVdkWMMMMMMMMMMWmQd&kmX7i5QWMMMmo<TFdV2l1<<<+71Izlc2WMMM##MM###M#M
|
||||
mQ8&V2TeeOJO2%XmMMWMWWguzYjtGFmWMMMWQ&WM#MD;)8mEb8tY]{[++]7<1JzlbMMMMMM#MWWMW#
|
||||
mmm@kAQgDSnVRRBW@L<1vT&8&Su55LeAWMMMMME&b0;:7WWmQU&0+)|/"+{+<oCYRMMMW&1""/7/xl
|
||||
WWWmWmWWWWWm8l7c0GdhR88R8FXXqANNWMM###M#Mc<JmMMWm@U&0o7<7+<czOn2QW%+"|//||))+4
|
||||
WWWWWWWWA=-)l8UbgXXqAk@KmmWWWWMM#M####M#Md8qM##MMWmbdn33YvluEmgL["+77+<+<"|<IB
|
||||
mWWWWmY.:<&AQ@@Q@@EmmWWWWMM#MMM#M######M#MWm@M####MWAq&%%D%C&WEXh3Jxl7<+|1]tL@
|
||||
WWWWB?'0@NKNEmmWWWWWMMMMMMWMMM#M#M#M######BzX@######MNXbbQqRg8F&&e8G32%5+i]YSm
|
||||
mN@@X2NmmmmWWWWMWMMMMMMM#MMWWmmWM##M#######mmQm######MWWWWND%g@$ASVFF88b=++C8&
|
||||
/|+=jFmWWWWWWMWWMMMMMMMMM#MM####M#################M###MmENhRqQR&bEb8exCJvollzj
|
||||
|)?<?x@mWWWWWMMMMMMMMMM##MM#M###MM###############MW@FdR&&%TeGhQb$Q&2xYvllllvj3
|
||||
]~'|I3T@mWWWWWWWMMMMMWMMM#M#M#MMM#MMM#M###M######MWK@gg8zv28hqEmbGuYvvlvvvzJ33
|
||||
@bh8VtO2L&QWWWWWWMMMWMMMM#M#MMMMMM#M##M####M#M#M##MmN@Q$8V&d@WWgCYocllvlvYjj32
|
||||
mmmmWmWmWmWWWWWWWWMMMMM#MMMMMM#MMMM#MMMM#####M#MM#MmBm@@@@mBAA@A0ll0u4vvvY3045
|
||||
mmmmmmmEQq@mmNba&@mWmWWWWMMMMMMMMMM#MMM#M##M#MWWWW@NWBmmBKdz@MW&tJvll2EWWB&qSd
|
||||
"""
|
||||
|
||||
PIC5 = """\
|
||||
VDGZGaGVZVVVGVGZVZGO0O3CYYvvvCYYC3C3YvCvlYCllvrlvvvrvrvIrlrIIIrl=r==I=7~
|
||||
9V9ZuV9uVZV99ZVZuttt3CCYlrlI=IIIrlllYlYrIrrYrIllvrrrlvlrIrrI==IIrIIIi=7`
|
||||
9utuOtt9ttu9utttuOt033YvvlvriI==ii<IrlrrrII=I=rrIIvIrllvIrrIr==III=i=<<`
|
||||
9tuOtOOtt00Ot00O000tC0Ot0vllII===<7iirrl=iii=<iI<Iii==IIII==i==i<<<<7++`
|
||||
u0O003O3CC33333YCCDFKNkFwFNKEqD3=ii7?++7<++i7?7?<7<7<7i<<=<7<<ii<<+7+77,
|
||||
9OC3CYCCCYvC3YY3uHmKqbQKBM##BkNKQZr=I=<+++???+++777777<7+7+<<+<<7i7++7}`
|
||||
t3CCCYCvYvlCYtUkNKQKEKkbBMMMMWBKEkYIl=iIi77777<<+<=<i77+<<<<i=<77<++7+(:
|
||||
3YClYrllYIlOEW#MWM##MmmNNWWWWMmNEkbY===I=i==i<i=====iii=<<77<<<<i=<+??}:
|
||||
O0YlvrIrlOhmWBMM###MNkAKBQmWEQQKNKKNC<+<<ii===I=irI=I=I=<==Iii==<7=i<++,
|
||||
OOvYlrIlDB#mWEKKKM###mmWKFmNKAKKkQKNq7}?+?+77<=iIIIr=I=====I=r=I===<7<+,
|
||||
03Y0lvIYDWWBMKNNW#####W#MMBQAQAQEKKNKd?}((}}}??+<<<rI==iirI=III=riiii<}:
|
||||
Ou30vlrr0QM##QdFKM###M##mWmmBKQQQNKKEQr*(*}*(*(}(}+777+iiiiI<i==i=r=ii7:
|
||||
uuO03v=iIlaXAkdlrRB#WWmAQMmEBEBmmEKBEN3([*[[[[[/[*(?++?7?+7+<<7<77i<77+:
|
||||
OOt0CYlIl<<iIYbHZCGBMkuC<OWBBMMBMBmmBK3}+((}*//[[[[*[?(((}(??}?}}}}7+?(.
|
||||
ut9tO0YvI=I=rYHH0YIVEN&ppuXB#W#MWmBN8Y3Y7}?}(([(*[**[**/*[/[[(*((}}***[:
|
||||
ZZ99ttCCYlrrIuOUGv<+rGaUavHW#MWWWEAqw8NQaul=7?+}?(((*[*****[[*/[*[[**[/:
|
||||
aGDZV9tt03vvlCY&X&07++}l}+uNEHd8wqEmMWAqXNKU0<7?}+??}(}([[*[**[*/(*/[//
|
||||
&pa&8GVZut0OYYYOdXF8VCIIY&dw&DpgEBNq&VXKHXdHHgv7i7<7777++?}}(}*}*([[*//.
|
||||
Fhdw&8a&aZZuuuOuwOXKKKQbqqF&&FKmmWBXDZi?IagqURbhIII=<i<7++???}}}+((}*[/:
|
||||
UhRhdR&Rp8a&DaVZGDhFwZZI=rZhFqkQKEHabC```~~^[uggROrrI=i<7+<7<7777+?(?(}`
|
||||
gXUgFUFRFFhww88aDDapah&VDFUkQKWmWE8hGi^`,``~`^;/ZUguri==<<<ii<<++777<7},
|
||||
qXXqAXHHqXHFRRRwRdRwpp&88&DhBmENKgZaU=^,`,```~~~-;CAFOiiii<ii<7i+++7i7?~
|
||||
qbbAkQbbAqXqXXXgu3I0&UqAFdwFmEEEBKXUUi^,,,,,,``,``~|pbhlii<<7==i7=}??7+-
|
||||
kkNkQQNQkQkANbHli(/(}}rGXAFhRmBKAQR8V+!~`,`,,,`~,`--~|dAZ===<<=<<<<<<77~
|
||||
QQQKQKNENKKKQkar?[;/**(+3hAUFFqEQNkkV</^,``,~`~~~~``-!}gqHI<7iii<<<i<7+;
|
||||
KNKKKEKEEBmEmqV<}[/*}(*?<vDqHggNKKkkpr/-,`-`~~^--^^^![iDXqhti==iI=iii7<!
|
||||
EBKNEBEEBmmmWKGvi*(?7?[[?ivakXXNEEKkFt=*!-^!^;|-~^/|[/+lFXgD8r<=I=I<i<i/
|
||||
BmEBBBNmmmmmEEgtl<7?+l?/*?IORNHAKKNQQhGvI77[[|!--~~^[*?ihgU8GD=<<ii=ii<*
|
||||
mWEKBBEBmmM#WWkOGtI+[=VI?+<38QKbKKENKmQUp9Ci}(*;;--``!/i9UUFwQa===Ii=i<(
|
||||
WmWmBBmWmmWWMMNDFZI?[(vwI7<lZqWKQEmBKNEEKbRa3Ii?*[!!--;+CwUggkEtvlr==Ir+
|
||||
###MWWmWWMmBWMm8gG<}*[7ZViirVUKmbABKNAXgkmmAU8uvi?*[[||([IhUg0YOYl==iir+
|
||||
WmmBWMMWWWBWMmV?[[}7**+lh3rr0aqHUwgBQNqdpRHkQkXwZ0vii<<~!/Zpw0vllYvlrI=?
|
||||
WWBBEBmWBmBEVvr7(;-;[<=rh9viIOkFhUpUD0i((+}<OdwpDu=[;|;;|;|l333C3YYlIrI<
|
||||
EmEBBBNBMBN0=ii+[!^^|/(?Y9Y7<rGEqXNAt=*;-~`~;IaqKAU89CI<?(/[}C03YvC3YllI
|
||||
KKEEEEBmmBAV=+7+[|!;/[*++=Y+/;!}9m#kI9?*^^^^^;|*ONENAgdVOl7([[lO3O0YCCYv
|
||||
KQKKEEEBEEkgC7ilI=<?*((}}7iYI[7=8X7}?Og37?}<l<}[;|CkBKAXRa0Y?}*?=0v03YYl
|
||||
QkkKKENBEEKkA83YCvvr=i+???7iCCrI[7YRWWMmERa3?}**[}(*OXEKNAX8VI<?*}OOOt0l
|
||||
AkNQKENEBEBBAAqV0vvYvrI=i77<il3tvqdMmKKAXUt<7?([;!^;/[ObBNQQqwZC=+tu9uu0
|
||||
qqbQKEBmEKKEKFFF&9OCYvr=Iri=rrY0uaR#Kg&pXbpGu3llIi77=v30XNKEXUhGua&V9Z9O
|
||||
bQXbqkkEBKKEmERQghau0CvlIrI=rrrvCtDHKF8DDF&VZuv3C=<?7?(i0kNBNkgqFRpGu9ut
|
||||
HQqHbkQKEEBEBWkG8KXwD90Cvvlrllvv0C39OG9tutVVOv=7((/;!|[}IGbFNEKENbHDt003
|
||||
AXbgqqkQBBBEKmMkw9hBgdaGuCvvvvYCClCtu[lYCY3OCl=+((/;|/[*7vUhRMBBmEb&aVO0
|
||||
XgbXgqbNEEBEBBBmBH&8MkFR8ZOOOY003C0tO;v7VDGVVtCrI<+(**(}}70=UEMMmQu[(lVG
|
||||
bqAAbkNQKEBBEW#MmmkUFWmAXhaZutOO3C3Y|[l}=qRFDDV3I7?(([(?i=0Cw0YXbv|YOuVZ
|
||||
bkQkkkNNEmWMMWMM##MKqX#BNAHh&DVuu0l;+r0**uXMqZ3v=+(*[//}=3&bQ9li/-(aGaGG
|
||||
XAkkANKEmmMWMM##M##MBEN#WNAqUwa9=/=CO9}<7YGhkM#NDv<777=IYVHWgvv?[rV&GV9t
|
||||
HbkKQAEEBm###########X0v0ZuOIi=uuV&V(O[ir0tDa93g##WUG3Ot98Q#KwV3rCGV&V9t
|
||||
UHAkkEKKKBm#####QKBW####WEqp0ll=iYC++Ilv0Y0uu3vI7lQ#WWM###M#MERGYlCZGZZ9
|
||||
RFHXbQkkNKE#Wkd&GZaXm#######WX8VOO3OtttO0333vl=777+vBBBWM##M#ERZ3vvtFaVt
|
||||
hhFFUXXbbkKq=rIlrCZpdAKBW#####BkRpDV9tt0CCrII77+<+7iCEM##KBMMmduYZV3G8G9
|
||||
FFUgFaD&qpI7=i=lYYCtu9u&Q#######mQXp&utOCCi==i<7==rY0FM#QgbWMEdY0wEwtu&D
|
||||
dU830OZ9Iii=Iv0D899u9OVhW#########mNUd&VtO3CYY330OuG&b#NggdgW#KgZt9Rh003
|
||||
R8VRZr====IOUWNNEKHkgXXqAQBW########MKkUd8&&&Da&&&8RbWbXgghUHXbKMKpZVUZV
|
||||
wF0Yv9hXXbqUdppw8wwwhFFgqAkkEKEWM#####WmKkbXUUUgqqkEkqqkqqgXgqXbgRdD&V9V
|
||||
dppa&8888Fd&D8pdhFhhhFUhbXbbANAkQkkEEBWM##MWWBBEEbXHUgXUgFXHAbbHXURUwp9t
|
||||
hFd8pdhRwh88dRdddRggqqHFUHHbQQANQNqbAAkbqbkXqXHXUUggRRhFhggqAqUFgUgFhphp
|
||||
&dhphRhdFw8ddFHUXHXXHqkXbUgRQQKQkbbAXXbAXHHgFRRFRwpdwUXFFHHHHFhRwwwd8GaG
|
||||
RgRRRFhhFRFUFggFHAqUXgbqXbXgHbAkQkXbbgFUhRw88pp88p8pdppw8&ggwwFw&8&&8D&9
|
||||
hFwwwdRggRUgUHUbXXqXbggbqHXgUggXUgUURhwww88&&88aVZVZGGDDZ&ZDpD8u9uZ&GGGZ
|
||||
"""
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
449
mpl/fibionacci.py
Normal file
449
mpl/fibionacci.py
Normal 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
444
mpl/fibionacci2.py
Normal 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
174
mpl/mpl-blit.py
Normal 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
163
mpl/mpl-draw.py
Normal 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
330
mpl/mpl-embedded.py
Normal 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()
|
||||
62
src/batch_rename.py
Normal file
62
src/batch_rename.py
Normal file
@@ -0,0 +1,62 @@
|
||||
""" flatex broker server """
|
||||
|
||||
import getopt
|
||||
import sys
|
||||
import os
|
||||
import re
|
||||
|
||||
import logging
|
||||
mylog = logging.getLogger('batch_rename')
|
||||
|
||||
class Usage(Exception):
|
||||
def __init__(self, message):
|
||||
Exception.__init__(message)
|
||||
|
||||
|
||||
class Error(Exception):
|
||||
def __init__(self, message):
|
||||
Exception.__init__(message)
|
||||
|
||||
# Star.Trek.The.Next.Generation.1x01-02.Encounter.At.Farpoint.DVDRip-AMC.[tvu.org.ru].avi
|
||||
# Star Trek TNG - 1x01-2 - Encounter At Farpoint - DVDRip-AMC.divx.avi
|
||||
|
||||
def main(argv = None):
|
||||
if argv == None:
|
||||
argv = sys.argv
|
||||
mylog.info("starting [%s]" % (argv[0],))
|
||||
try:
|
||||
try:
|
||||
opts, args = getopt.getopt(argv[1:], "h", ["help"])
|
||||
print "opts: ", opts, "args:", args
|
||||
except getopt.error, msg:
|
||||
raise Usage(msg)
|
||||
# more code, unchanged
|
||||
p = re.compile("Star\.Trek\.The\.Next\.Generation.(.*?)\.(.*)\.(DVDRip-.*)\.\[tvu.org.ru\]\.avi")
|
||||
tng = "e:\\share\\movies\\star trek tng"
|
||||
os.chdir(tng)
|
||||
for (dirpath, dirnames, filenames) in os.walk(tng):
|
||||
for f in filenames:
|
||||
mot = re.match(p, f)
|
||||
if mot is not None:
|
||||
# print mot.group()
|
||||
print mot.groups()
|
||||
ver = mot.group(1)
|
||||
title0 = mot.group(2)
|
||||
title1 = title0.replace('.', ' ')
|
||||
nf = "Star Trek TNG - %s - %s - %s.divx.avi" % (ver, title1, mot.group(3))
|
||||
# os.rename(f, nf)
|
||||
print 'ren "%s" "%s"' % (f, nf)
|
||||
|
||||
except Error, err:
|
||||
mylog.error(err.message)
|
||||
return 1
|
||||
except Usage, err:
|
||||
mylog.error(err.message)
|
||||
mylog.error("for help use --help")
|
||||
return 2
|
||||
|
||||
if __name__ == '__main__':
|
||||
logging.basicConfig(level=logging.DEBUG,
|
||||
format='%(asctime)s.%(msecs)03d %(levelname)-8s %(message)s',
|
||||
datefmt='%H:%M:%S')
|
||||
sys.exit(main())
|
||||
6
src/ftpget.py
Normal file
6
src/ftpget.py
Normal file
@@ -0,0 +1,6 @@
|
||||
from ftplib import FTP
|
||||
|
||||
ftp = FTP('ftp.asstr.org') # connect to host, default port
|
||||
ftp.login() # user anonymous, passwd anonymous@
|
||||
print ftp.getwelome()
|
||||
ftp.retrbinary('RETR README', open('README', 'wb').write)
|
||||
97
src/histogram.py
Normal file
97
src/histogram.py
Normal file
@@ -0,0 +1,97 @@
|
||||
""" walk histogram
|
||||
"""
|
||||
|
||||
import sys
|
||||
import re
|
||||
import datetime
|
||||
|
||||
mol = re.compile("\S+\s(\S+?)\|.{5}(.{6}).\|(.*)\|(.*)")
|
||||
|
||||
def main(argv = None):
|
||||
if argv == None:
|
||||
argv = sys.argv
|
||||
ifn = "e:/livefeed/20070829/GDAXI.csv"
|
||||
ofn = "e:/eclipse/workspace/filter/var/GDAXI_histogram.csv"
|
||||
tick_list = [ ]
|
||||
histogram = { }
|
||||
print "Converting [%s] to [%s]" % (ifn, ofn)
|
||||
try:
|
||||
ifh = open(ifn, "r")
|
||||
ofh = open(ofn, "w")
|
||||
except IOError:
|
||||
print "open [%s] failed" % ifn
|
||||
return 2
|
||||
try:
|
||||
for line in ifh:
|
||||
tick_list.append(parseCsv(line))
|
||||
for i in xrange(1, len(tick_list)):
|
||||
diff = tick_list[i].last - tick_list[i-1].last
|
||||
key = int( diff * 100 )
|
||||
if key not in histogram:
|
||||
histogram[key] = 1
|
||||
else:
|
||||
histogram[key] += 1
|
||||
# for key in sorted(histogram.keys()):
|
||||
for i in xrange(-1000, 1000):
|
||||
if i in histogram:
|
||||
print >> ofh, float(i)/100, ",", histogram[i]
|
||||
else:
|
||||
print >> ofh, float(i)/100, ",0"
|
||||
finally:
|
||||
ifh.close()
|
||||
ofh.close()
|
||||
print "Done."
|
||||
|
||||
time_pattern = re.compile("(..):(..):(..).(\d+)")
|
||||
|
||||
def parseCsv(line):
|
||||
flds = line.split(',')
|
||||
mot = re.match(time_pattern, flds[0])
|
||||
(hh, mm, ss, ms) = mot.group(1, 2, 3, 4)
|
||||
time = datetime.time(int(hh), int(mm), int(ss), int(ms)*1000)
|
||||
# pid = flds[1]
|
||||
bid = flds[2]
|
||||
ask = flds[3]
|
||||
last = flds[4]
|
||||
return Tick(time, float(bid), float(ask), float(last))
|
||||
|
||||
class Tick:
|
||||
""" VDO helper class """
|
||||
def __init__(self, ti, bid, ask, last):
|
||||
self.time = ti
|
||||
self.bid = bid
|
||||
self.ask = ask
|
||||
self.last= last
|
||||
|
||||
def __cmp__(self, other):
|
||||
return cmp(self.time, other.time)
|
||||
|
||||
class Roi:
|
||||
""" VDO helper class """
|
||||
def __init__(self, buy_time, sell_time, pnl):
|
||||
self.buy_time = buy_time
|
||||
self.sell_time = sell_time
|
||||
self.pnl = pnl
|
||||
|
||||
def pnl_per_minute(self):
|
||||
dt = time_in_minutes(self.sell_time) - time_in_minutes(self.buy_time)
|
||||
try:
|
||||
ppm = self.pnl / dt
|
||||
except ZeroDivisionError:
|
||||
return self.pnl
|
||||
return ppm
|
||||
|
||||
def __cmp__(self, other):
|
||||
return cmp(self.pnl_per_minute(), other.pnl_per_minute())
|
||||
|
||||
def __repr__(self):
|
||||
return "%s,%s,%.2f,%.2f" % (self.buy_time, self.sell_time,
|
||||
self.pnl, self.pnl_per_minute())
|
||||
|
||||
|
||||
def time_in_minutes(ti):
|
||||
return ti.hour * 60 + ti.minute + float(ti.second) / 60
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main(sys.argv))
|
||||
35
src/pricefeed.py
Normal file
35
src/pricefeed.py
Normal file
@@ -0,0 +1,35 @@
|
||||
""" pricefeed file filter
|
||||
*.log: "20070905 09:04:56.841|DE000DB0M091|4.430|4.440"
|
||||
*.csv: "09:04:56.841,DB0M09,4.430,4.440"
|
||||
"""
|
||||
|
||||
import sys
|
||||
import re
|
||||
|
||||
mol = re.compile("\S+\s(\S+?)\|.{5}(.{6}).\|(.*)\|(.*)")
|
||||
|
||||
def main(argv = None):
|
||||
if argv == None:
|
||||
argv = sys.argv
|
||||
if (len(argv) != 2):
|
||||
print "Usage: filter.py <filename.log>"
|
||||
return 2
|
||||
ifn = argv[1]
|
||||
ofn = "".join((ifn.split(".")[0], ".csv"))
|
||||
print "Converting [%s] to [%s]" % (ifn, ofn)
|
||||
try:
|
||||
ifh = open(ifn, "r")
|
||||
ofh = open(ofn, "w")
|
||||
except IOError:
|
||||
print "open [%s] failed" % ifn
|
||||
return 2
|
||||
try:
|
||||
for line in ifh:
|
||||
flds = mol.match(line)
|
||||
print >>ofh, ",".join(flds.groups())
|
||||
finally:
|
||||
ifh.close()
|
||||
ofh.close()
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main(sys.argv))
|
||||
94
src/roimatrix.py
Normal file
94
src/roimatrix.py
Normal file
@@ -0,0 +1,94 @@
|
||||
""" roi matrix
|
||||
"""
|
||||
|
||||
import sys
|
||||
import re
|
||||
import datetime
|
||||
|
||||
mol = re.compile("\S+\s(\S+?)\|.{5}(.{6}).\|(.*)\|(.*)")
|
||||
|
||||
def main(argv = None):
|
||||
if argv == None:
|
||||
argv = sys.argv
|
||||
ifn = "e:/livefeed/20070829/GDAXI.csv"
|
||||
ofn = "e:/eclipse/workspace/filter/var/GDAXI_roi.csv"
|
||||
tick_list = [ ]
|
||||
roi_list = [ ]
|
||||
print "Converting [%s] to [%s]" % (ifn, ofn)
|
||||
try:
|
||||
ifh = open(ifn, "r")
|
||||
ofh = open(ofn, "w")
|
||||
except IOError:
|
||||
print "open [%s] failed" % ifn
|
||||
return 2
|
||||
try:
|
||||
for line in ifh:
|
||||
tick_list.append(parseCsv(line))
|
||||
for (i, buy_tick) in enumerate(tick_list[0::300]):
|
||||
print buy_tick.time
|
||||
for sell_tick in tick_list[0::300]:
|
||||
if (buy_tick > sell_tick):
|
||||
continue
|
||||
pnl = ( sell_tick.last - buy_tick.last ) * 25.0 - 11.80
|
||||
# print buy_tick.last, sell_tick.last, pnl
|
||||
roi_list.append(Roi(buy_tick.time, sell_tick.time, pnl))
|
||||
for roi in roi_list:
|
||||
print >> ofh, str(roi)
|
||||
finally:
|
||||
ifh.close()
|
||||
ofh.close()
|
||||
print "Done."
|
||||
|
||||
time_pattern = re.compile("(..):(..):(..).(\d+)")
|
||||
|
||||
def parseCsv(line):
|
||||
flds = line.split(',')
|
||||
mot = re.match(time_pattern, flds[0])
|
||||
(hh, mm, ss, ms) = mot.group(1, 2, 3, 4)
|
||||
time = datetime.time(int(hh), int(mm), int(ss), int(ms)*1000)
|
||||
# pid = flds[1]
|
||||
bid = flds[2]
|
||||
ask = flds[3]
|
||||
last = flds[4]
|
||||
return Tick(time, float(bid), float(ask), float(last))
|
||||
|
||||
class Tick:
|
||||
""" VDO helper class """
|
||||
def __init__(self, ti, bid, ask, last):
|
||||
self.time = ti
|
||||
self.bid = bid
|
||||
self.ask = ask
|
||||
self.last= last
|
||||
|
||||
def __cmp__(self, other):
|
||||
return cmp(self.time, other.time)
|
||||
|
||||
class Roi:
|
||||
""" VDO helper class """
|
||||
def __init__(self, buy_time, sell_time, pnl):
|
||||
self.buy_time = buy_time
|
||||
self.sell_time = sell_time
|
||||
self.pnl = pnl
|
||||
|
||||
def pnl_per_minute(self):
|
||||
dt = time_in_minutes(self.sell_time) - time_in_minutes(self.buy_time)
|
||||
try:
|
||||
ppm = self.pnl / dt
|
||||
except ZeroDivisionError:
|
||||
return self.pnl
|
||||
return ppm
|
||||
|
||||
def __cmp__(self, other):
|
||||
return cmp(self.pnl_per_minute(), other.pnl_per_minute())
|
||||
|
||||
def __repr__(self):
|
||||
return "%s,%s,%.2f,%.2f" % (self.buy_time, self.sell_time,
|
||||
self.pnl, self.pnl_per_minute())
|
||||
|
||||
|
||||
def time_in_minutes(ti):
|
||||
return ti.hour * 60 + ti.minute + float(ti.second) / 60
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main(sys.argv))
|
||||
52
src/wget_batch.py
Normal file
52
src/wget_batch.py
Normal file
@@ -0,0 +1,52 @@
|
||||
""" broker quote request recorder engine """
|
||||
|
||||
import logging
|
||||
import getopt
|
||||
import sys
|
||||
import datetime
|
||||
|
||||
mylog = logging.getLogger()
|
||||
|
||||
|
||||
class Usage(Exception):
|
||||
def __init__(self, message):
|
||||
Exception.__init__(message)
|
||||
|
||||
|
||||
class Error(Exception):
|
||||
def __init__(self, message):
|
||||
Exception.__init__(message)
|
||||
|
||||
|
||||
def main(argv = None):
|
||||
if argv == None:
|
||||
argv = sys.argv
|
||||
mylog.info("starting [%s]" % (argv[0],))
|
||||
try:
|
||||
try:
|
||||
opts, args = getopt.getopt(argv[1:], "h", ["help"])
|
||||
print "opts: ", opts, "args:", args
|
||||
except getopt.error, msg:
|
||||
raise Usage(msg)
|
||||
# set up stderr logging
|
||||
logging.basicConfig(level=logging.DEBUG,
|
||||
format='%(asctime)s.%(msecs)03d %(levelname)-8s %(message)s',
|
||||
datefmt='%H:%M:%S')
|
||||
# main code starts here
|
||||
ofh = open("e:/install/asstr_get", "w")
|
||||
for i in xrange(56546,57096):
|
||||
# print >> ofh, "wget http://www.literotica.com/stories/showstory.php?id=%i" % i
|
||||
print >> ofh, "wget http://www.asstr.org/files/Collections/Alt.Sex.Stories.Moderated/Year2007/%i" % i
|
||||
ofh.close()
|
||||
|
||||
except Error, err:
|
||||
mylog.error(err.message)
|
||||
return 1
|
||||
except Usage, err:
|
||||
mylog.error(err.message)
|
||||
mylog.error("for help use --help")
|
||||
return 2
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
|
||||
Reference in New Issue
Block a user