summaryrefslogtreecommitdiff
path: root/invest-applet/invest/chart.py
diff options
context:
space:
mode:
authorPerberos <[email protected]>2011-11-14 18:24:48 -0300
committerPerberos <[email protected]>2011-11-14 18:24:48 -0300
commit312ba610a1e98fc656fb58178227d7d45a64494e (patch)
tree54a3c2b6084c80e63fb0526c6e7b8e01627acbd7 /invest-applet/invest/chart.py
downloadmate-applets-312ba610a1e98fc656fb58178227d7d45a64494e.tar.bz2
mate-applets-312ba610a1e98fc656fb58178227d7d45a64494e.tar.xz
initial
Diffstat (limited to 'invest-applet/invest/chart.py')
-rw-r--r--invest-applet/invest/chart.py257
1 files changed, 257 insertions, 0 deletions
diff --git a/invest-applet/invest/chart.py b/invest-applet/invest/chart.py
new file mode 100644
index 00000000..c6caff74
--- /dev/null
+++ b/invest-applet/invest/chart.py
@@ -0,0 +1,257 @@
+#!/usr/bin/env python
+
+import gtk, gtk.gdk
+import gobject
+import os
+import invest
+from gettext import gettext as _
+from invest import *
+import sys
+from os.path import join
+import urllib
+from threading import Thread
+import time
+
+AUTOREFRESH_TIMEOUT = 20*60*1000 # 15 minutes
+
+# based on http://www.johnstowers.co.nz/blog/index.php/2007/03/12/threading-and-pygtk/
+class _IdleObject(gobject.GObject):
+ """
+ Override gobject.GObject to always emit signals in the main thread
+ by emmitting on an idle handler
+ """
+ def __init__(self):
+ gobject.GObject.__init__(self)
+
+ def emit(self, *args):
+ gobject.idle_add(gobject.GObject.emit,self,*args)
+
+class ImageRetriever(Thread, _IdleObject):
+ """
+ Thread which uses gobject signals to return information
+ to the GUI.
+ """
+ __gsignals__ = {
+ "completed": (
+ gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, []),
+ # FIXME: should we be making use of this?
+ #"progress": (
+ # gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, [
+ # gobject.TYPE_FLOAT]) #percent complete
+ }
+
+ def __init__(self, image_url):
+ Thread.__init__(self)
+ _IdleObject.__init__(self)
+ self.image_url = image_url
+ self.retrieved = False
+
+ def run(self):
+ self.image = gtk.Image()
+ try: sock = urllib.urlopen(self.image_url, proxies = invest.PROXY)
+ except Exception, msg:
+ invest.debug("Error while opening %s: %s" % (self.image_url, msg))
+ else:
+ loader = gtk.gdk.PixbufLoader()
+ loader.connect("closed", lambda loader: self.image.set_from_pixbuf(loader.get_pixbuf()))
+ loader.write(sock.read())
+ sock.close()
+ loader.close()
+ self.retrieved = True
+ self.emit("completed")
+
+# p:
+# eX = Exponential Moving Average
+# mX = Moving Average
+# b = Bollinger Bands Overlay
+# v = Volume Overlay
+# p = Parabolic SAR overlay
+# s = Splits Overlay
+# q:
+# l = Line
+# c = Candles
+# b = Bars
+# l:
+# on = Logarithmic
+# off = Linear
+# z:
+# l = Large
+# m = Medium
+# t:
+# Xd = X Days
+# Xm = X Months
+# Xy = X Years
+# a:
+# fX = MFI X days
+# ss = Slow Stochastic
+# fs = Fast Stochastic
+# wX = W%R X Days
+# mX-Y-Z = MACD X Days, Y Days, Signal
+# pX = ROC X Days
+# rX = RSI X Days
+# v = Volume
+# vm = Volume +MA
+# c:
+# X = compare with X
+#
+
+class FinancialChart:
+ def __init__(self, ui):
+ self.ui = ui
+
+ #Time ranges of the plot
+ self.time_ranges = ["1d", "5d", "3m", "6m", "1y", "5y", "my"]
+
+ # Window Properties
+ win = ui.get_object("window")
+ win.set_title(_("Financial Chart"))
+
+ try:
+ pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(join(invest.ART_DATA_DIR, "invest_neutral.svg"), 96,96)
+ self.ui.get_object("plot").set_from_pixbuf(pixbuf)
+ except Exception, msg:
+ invest.debug("Could not load 'invest-neutral.svg' file: %s" % msg)
+ pass
+
+ # Defaut comboboxes values
+ for widget in ["t", "q"]:
+ ui.get_object(widget).set_active(0)
+
+ # Connect every option widget to its corresponding change signal
+ symbolentry = ui.get_object("s")
+ refresh_chart_callback = lambda w: self.on_refresh_chart()
+
+ for widgets, signal in [
+ (("pm5","pm10","pm20","pm50","pm100","pm200",
+ "pe5","pe10", "pe20","pe50","pe100","pe200",
+ "pb","pp","ps","pv",
+ "ar","af","ap","aw","am","ass","afs","av","avm"), "toggled"),
+ (("t", "q"), "changed"),
+ (("s",), "activate"),
+ ]:
+ for widget in widgets:
+ ui.get_object(widget).connect(signal, refresh_chart_callback)
+
+ ui.get_object("progress").hide()
+
+ # Connect auto-refresh widget
+ self.autorefresh_id = 0
+ ui.get_object("autorefresh").connect("toggled", self.on_autorefresh_toggled)
+
+ def on_refresh_chart(self, from_timer=False):
+ tickers = self.ui.get_object("s").get_text()
+
+ if tickers.strip() == "":
+ return True
+
+ # FIXME: We don't just do US stocks, so we can't be this
+ # simplistic about it, but it is a good idea.
+ #if from_timer and not ustime.hour_between(9, 16):
+ # return True
+
+ tickers = [ticker.strip().upper() for ticker in tickers.split(' ') if ticker != ""]
+
+ # Update Window Title ------------------------------------------------------
+ win = self.ui.get_object("window")
+ title = _("Financial Chart - %s")
+ titletail = ""
+ for ticker in tickers:
+ titletail += "%s / " % ticker
+ title = title % titletail
+
+ win.set_title(title[:-3])
+
+ # Detect Comparison or simple chart ----------------------------------------
+ opt = ""
+ for ticker in tickers[1:]:
+ opt += "&c=%s" % ticker
+
+ # Create the overlay string ------------------------------------------------
+ p = ""
+ for name, param in [
+ ("pm5", 5),
+ ("pm10", 10),
+ ("pm20", 20),
+ ("pm50", 50),
+ ("pm100", 100),
+ ("pm200", 200),
+ ("pe5", 5),
+ ("pe10", 10),
+ ("pe20", 20),
+ ("pe50", 50),
+ ("pe100", 100),
+ ("pe200", 200),
+ ("pb", ""),
+ ("pp", ""),
+ ("ps", ""),
+ ("pv", ""),
+ ]:
+ if self.ui.get_object(name).get_active():
+ p += "%s%s," % (name[1], param)
+
+ # Create the indicators string ---------------------------------------------
+ a = ""
+ for name, param in [
+ ("ar", 14),
+ ("af", 14),
+ ("ap", 12),
+ ("aw", 14),
+ ("am", "26-12-9"),
+ ("ass", ""),
+ ("afs", ""),
+ ("av", ""),
+ ("avm", ""),
+ ]:
+ if self.ui.get_object(name).get_active():
+ a += "%s%s," % (name[1:], param)
+
+ # Create the image URL -----------------------------------------------------
+ chart_base_url = "http://ichart.europe.yahoo.com/z?s=%(s)s&t=%(t)s&q=%(q)s&l=%(l)s&z=%(z)s&p=%(p)s&a=%(a)s%(opt)s"
+ url = chart_base_url % {
+ "s": tickers[0],
+ "t": self.time_ranges[self.ui.get_object("t").get_active()],
+ "q": self.ui.get_object("q").get_active_text(),
+ "l": "off",
+ "z": "l",
+ "p": p,
+ "a": a,
+ "opt": opt,
+ }
+
+ # Download and display the image -------------------------------------------
+ progress = self.ui.get_object("progress")
+ progress.set_text(_("Opening Chart"))
+ progress.show()
+
+ image_retriever = ImageRetriever(url)
+ image_retriever.connect("completed", self.on_retriever_completed)
+ image_retriever.start()
+
+ # Update timer if needed
+ self.on_autorefresh_toggled(self.ui.get_object("autorefresh"))
+ return True
+
+ def on_retriever_completed(self, retriever):
+ self.ui.get_object("plot").set_from_pixbuf(retriever.image.get_pixbuf())
+ progress = self.ui.get_object("progress")
+ if retriever.retrieved == True:
+ progress.set_text(_("Chart downloaded"))
+ else:
+ progress.set_text(_("Chart could not be downloaded"))
+
+ def on_autorefresh_toggled(self, autorefresh):
+ if self.autorefresh_id != 0:
+ gobject.source_remove(self.autorefresh_id)
+ self.autorefresh_id = 0
+
+ if autorefresh.get_active():
+ self.autorefresh_id = gobject.timeout_add(AUTOREFRESH_TIMEOUT, self.on_refresh_chart, True)
+
+def show_chart(tickers):
+ ui = gtk.Builder();
+ ui.add_from_file(os.path.join(invest.BUILDER_DATA_DIR, "financialchart.ui"))
+ chart = FinancialChart(ui)
+ ui.get_object("s").set_text(' '.join(tickers))
+ chart.on_refresh_chart()
+ return ui.get_object("window")
+