itrade_wxquote.py :  » Business-Application » iTrade » itrade » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Business Application » iTrade 
iTrade » itrade » itrade_wxquote.py
#!/usr/bin/env python
# ============================================================================
# Project Name : iTrade
# Module Name  : itrade_wxquote.py
#
# Description: wxPython quote display
#
# The Original Code is iTrade code (http://itrade.sourceforge.net).
#
# The Initial Developer of the Original Code is  Gilles Dumortier.
#
# Portions created by the Initial Developer are Copyright (C) 2004-2008 the
# Initial Developer. All Rights Reserved.
#
# Contributor(s):
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; see http://www.gnu.org/licenses/gpl.html
#
# History       Rev   Description
# 2005-03-27    dgil  Wrote it from scratch
# 2005-04-03    dgil  Add quote selector
# 2005-05-29    dgil  Move liste quote stuff to module itrade_wxlistquote.py
# ============================================================================

# ============================================================================
# Imports
# ============================================================================

# python system
import os
import logging
import webbrowser
import datetime
import locale

# iTrade system
from itrade_logging import *
from itrade_quotes import *
from itrade_local import message,setLocale
from itrade_config import *

# wxPython system
import itrade_wxversion
import wx
import wx.grid as gridlib
import wxaddons.sized_controls as sc

# matplotlib system
import matplotlib

from matplotlib.dates import date2num,num2date
from myfinance import candlestick,plot_day_summary2,candlestick2,index_bar,volume_overlay2,plot_day_summary3

# iTrade wxPython system
from itrade_wxhtml import *
from itrade_wxmixin import iTrade_wxFrame
from itrade_wxgraph import iTrade_wxPanelGraph,fmtVolumeFunc,fmtVolumeFunc0
from itrade_wxlive import iTrade_wxLive,iTrade_wxLiveMixin,EVT_UPDATE_LIVE
from itrade_wxselectquote import select_iTradeQuote
from itrade_wxpropquote import iTradeQuotePropertiesPanel
from itrade_wxdecision import iTrade_wxDecision

# ============================================================================
# iTradeQuoteToolbar
#
# ============================================================================

class iTradeQuoteToolbar(wx.ToolBar):

    def __init__(self,parent,id):
        wx.ToolBar.__init__(self,parent,id,size = (120,32), style = wx.TB_HORIZONTAL | wx.NO_BORDER | wx.TB_FLAT)
        self.m_parent = parent
        self.m_Throbber = None
        self._init_toolbar()

    def _init_toolbar(self):
        self._NTB2_EXIT = wx.NewId()
        self._NTB2_SELECT = wx.NewId()
        self._NTB2_REFRESH = wx.NewId()

        self.SetToolBitmapSize(wx.Size(24,24))
        self.AddSimpleTool(self._NTB2_EXIT, wx.ArtProvider.GetBitmap(wx.ART_CROSS_MARK, wx.ART_TOOLBAR),
                           message('main_close'), message('main_desc_close'))
        self.AddControl(wx.StaticLine(self, -1, size=(-1,23), style=wx.LI_VERTICAL))
        self.AddSimpleTool(self._NTB2_SELECT, wx.Bitmap(os.path.join(itrade_config.dirRes, 'quotes.png')),
                           message('quote_select_title'), message('quote_select_title'))
        self.AddSimpleTool(self._NTB2_REFRESH, wx.Bitmap(os.path.join(itrade_config.dirRes, 'refresh.png')),
                           message('main_view_refresh'), message('main_view_desc_refresh'))

        wx.EVT_TOOL(self, self._NTB2_EXIT, self.exit)
        wx.EVT_TOOL(self, self._NTB2_SELECT, self.select)
        wx.EVT_TOOL(self, self._NTB2_REFRESH, self.refresh)
        self.Realize()

    def refresh(self, event):
        if (not self.m_Throbber) or (not self.m_Throbber.Running()):
            # refresh
            self.m_parent.OnRefresh(event)

    def OnStop(self):
        # stop animation
        if self.m_Throbber:
            self.m_Throbber.Rest()

    def OnStart(self):
        # start animation
        if self.m_Throbber:
            self.m_Throbber.Start()

    def select(self,event):
        self.m_parent.OnSelectQuote(event)

    def exit(self,event):
        self.m_parent.OnExit(event)

# ============================================================================
# iTradeQuoteInfoWindow
#
#   Display informations on a specific quote
# ============================================================================

def exists(filename):
    try:
        f = open(filename)
        f.close()
        return True
    except:
        return False

class iTradeQuoteInfoWindow(sc.SizedPanel):

    def __init__(self,parent,id,size,quote):
        sc.SizedPanel.__init__(self,parent,id, size=size,style=wx.SIMPLE_BORDER | wx.TAB_TRAVERSAL | wx.NO_FULL_REPAINT_ON_RESIZE)

        self.m_parent = parent
        self.m_quote = quote
        self.m_logo = None

        self.SetSizerType("vertical")

        # Toolbar
        self.m_toolbar = iTradeQuoteToolbar(self, wx.NewId())

        # separator
        self.wxLine = wx.StaticLine(self, -1, size=(20,-1), style=wx.LI_HORIZONTAL)
        self.wxLine.SetSizerProps(expand=True)

        # resizable pane
        pane = sc.SizedPanel(self, -1)
        pane.SetSizerType("horizontal")
        pane.SetSizerProps(expand=True)

        self.wxTicker = wx.StaticText(pane, -1, "???")
        self.wxTicker.SetSizerProps(valign='center')

        self.wxLogo = wx.StaticBitmap(pane, -1)
        self.wxLogo.SetSizerProps(valign='center')

        # separator
        line = wx.StaticLine(self, -1, size=(20,-1), style=wx.LI_HORIZONTAL)
        line.SetSizerProps(expand=True)

        self.wxDate = wx.StaticText(self, -1, "???")

        # resizable pane
        pane = sc.SizedPanel(self, -1)
        pane.SetSizerType("form")
        pane.SetSizerProps(expand=True)

        txt = wx.StaticText(pane, -1, message('variation'))
        self.wxPercent = wx.StaticText(pane, -1, "??? %")

        txt = wx.StaticText(pane, -1, message('last'))
        self.wxLast = wx.StaticText(pane, -1, "???")

        txt = wx.StaticText(pane, -1, message('open'))
        self.wxOpen = wx.StaticText(pane, -1, "???")

        txt = wx.StaticText(pane, -1, message('high'))
        self.wxHigh = wx.StaticText(pane, -1, "???")

        txt = wx.StaticText(pane, -1, message('low'))
        self.wxLow = wx.StaticText(pane, -1, "???")

        txt = wx.StaticText(pane, -1, message('volume'))
        self.wxVolume = wx.StaticText(pane, -1, "???")

        txt = wx.StaticText(pane, -1, message('prev'))
        self.wxPrev = wx.StaticText(pane, -1, "???")

        txt = wx.StaticText(pane, -1, message('cmp'))
        self.wxCmp = wx.StaticText(pane, -1, "???")

        # separator
        line = wx.StaticLine(self, -1, size=(20,-1), style=wx.LI_HORIZONTAL)
        line.SetSizerProps(expand=True)

        # resizable pane
        pane = sc.SizedPanel(self, -1)
        pane.SetSizerType("form")
        pane.SetSizerProps(expand=True)

        txt = wx.StaticText(pane, -1, message('status'))
        self.wxStatus = wx.StaticText(pane, -1, "")

        txt = wx.StaticText(pane, -1, message('reopen'))
        self.wxReopen = wx.StaticText(pane, -1, "???")

        txt = wx.StaticText(pane, -1, message('high_threshold'))
        self.wxHigh_threshold = wx.StaticText(pane, -1, "???")

        txt = wx.StaticText(pane, -1, message('low_threshold'))
        self.wxLow_threshold = wx.StaticText(pane, -1, "???")

        # separator
        line = wx.StaticLine(self, -1, size=(20,-1), style=wx.LI_HORIZONTAL)
        line.SetSizerProps(expand=True)

        self.refresh()

    def OnSelectQuote(self,event):
        self.m_parent.SelectQuote()

    def OnRefresh(self,event):
        self.m_parent.refresh()

    def OnExit(self, evt):
        self.m_parent.OnExit(evt)

    def suffixLogo(self,ext):
        return '%s-%s.%s' % (self.m_quote.ticker().lower(),self.m_quote.market().lower(),ext)

    def paintLogo(self):
        if self.m_logo == None:

            fn = os.path.join(itrade_config.dirImageData,self.suffixLogo('gif'))
            if not exists(fn):
                fn = os.path.join(itrade_config.dirImageData,self.suffixLogo('png'))
            if not exists(fn):
                fn = os.path.join(itrade_config.dirImageData,self.suffixLogo('bmp'))
            if not exists(fn):
                fn = os.path.join(itrade_config.dirImageData,self.suffixLogo('jpg'))
            self.wxLogo.SetBitmap(wx.NullBitmap)
            if exists(fn):
                self.m_logo = wx.Bitmap(fn)
                self.wxLogo.SetBitmap(self.m_logo)

    def paint(self):
        # paint logo (if any)
        self.paintLogo()

        # paint fields
        self.wxTicker.SetLabel(self.m_quote.ticker())
        self.wxDate.SetLabel("%s | %s | %s" % (self.m_quote.sv_date(bDisplayShort=True),self.m_quote.sv_clock(),self.m_quote.sv_type_of_clock()))

        percent = self.m_quote.nv_percent()
        if percent==0:
            self.wxPercent.SetForegroundColour(wx.BLACK)
            self.wxLast.SetForegroundColour(wx.BLACK)
        elif percent<0:
            self.wxPercent.SetForegroundColour(wx.RED)
            self.wxLast.SetForegroundColour(wx.RED)
        else:
            self.wxPercent.SetForegroundColour(wx.BLUE)
            self.wxLast.SetForegroundColour(wx.BLUE)
        self.wxPercent.SetLabel(self.m_quote.sv_percent())

        self.wxLast.SetLabel(self.m_quote.sv_close(bDispCurrency=True))

        if self.m_quote.hasTraded():
            self.wxOpen.SetLabel(self.m_quote.sv_open())
            self.wxHigh.SetLabel(self.m_quote.sv_high())
            self.wxLow.SetLabel(self.m_quote.sv_low())
            self.wxVolume.SetLabel(self.m_quote.sv_volume())
        else:
            self.wxOpen.SetLabel(" ---.-- ")
            self.wxHigh.SetLabel(" ---.-- ")
            self.wxLow.SetLabel(" ---.-- ")
            self.wxVolume.SetLabel(" ---------- ")

        self.wxPrev.SetLabel(self.m_quote.sv_prevclose())
        self.wxCmp.SetLabel(self.m_quote.sv_waq())

        status = self.m_quote.sv_status()
        if status=="OK":
            self.wxStatus.SetForegroundColour(wx.BLUE)
        else:
            self.wxStatus.SetForegroundColour(wx.RED)

        self.wxStatus.SetLabel(status)
        self.wxReopen.SetLabel(self.m_quote.sv_reopen())
        self.wxHigh_threshold.SetLabel("%.2f" % self.m_quote.high_threshold())
        self.wxLow_threshold.SetLabel("%.2f" % self.m_quote.low_threshold())

    def refresh(self,nquote=None,live=False):
        debug('QuoteInfoWindow::refresh %s' % self.m_quote.ticker())

        # update the logo if needed
        fit = False
        if nquote and nquote<>self.m_quote:
            if itrade_config.verbose:
                print 'QuoteInfoWinfow::refresh New Quote %s - live=%s' % (nquote.ticker(),live)
            self.m_quote = nquote
            self.m_logo = None
            fit = True

        # __x to be removed - no need to update or compute at this stage
        if not itrade_config.experimental:
            if not live:
                self.m_quote.update()
            self.m_quote.compute()

        # paint the content
        if itrade_config.verbose:
            print 'QuoteInfoWinfow::refresh Paint Quote %s - live=%s' % (self.m_quote.ticker(),live)
        self.paint()

        # fit but stay on the space given by the parent
        if fit:
            size = self.GetSize()
            self.Fit()
            self.SetMinSize(size)
            self.SetSize(size)

# ============================================================================
# iTradeQuoteTablePanel
#
#   Table
# ============================================================================

class CustomDataTable(gridlib.PyGridTableBase):

    def __init__(self,quote):
        gridlib.PyGridTableBase.__init__(self)

        self.colLabels = [ message('date'),
                           message('volume'),
                           message('open'),
                           message('low'),
                           message('high'),
                           message('last'),
                         ]

        self.dataTypes = [gridlib.GRID_VALUE_STRING,
                          gridlib.GRID_VALUE_FLOAT + ':12,0',
                          gridlib.GRID_VALUE_FLOAT + ':6,2',
                          gridlib.GRID_VALUE_FLOAT + ':6,2',
                          gridlib.GRID_VALUE_FLOAT + ':6,2',
                          gridlib.GRID_VALUE_FLOAT + ':6,2',
                          ]

        self.data = []

        for trade in quote.trades().trades():
            self.data.append([trade.date(),trade.nv_volume(),trade.nv_open(),trade.nv_low(),trade.nv_high(),trade.nv_close()])

    # ---[ required methods for the wxPyGridTableBase interface ] -------------------

    def GetNumberRows(self):
        return len(self.data) + 1

    def GetNumberCols(self):
        return len(self.data[0])

    def IsEmptyCell(self, row, col):
        try:
            return not self.data[row][col]
        except IndexError:
            return True

    # Get/Set values in the table.  The Python version of these
    # methods can handle any data-type, (as long as the Editor and
    # Renderer understands the type too,) not just strings as in the
    # C++ version.
    def GetValue(self, row, col):
        try:
            return self.data[row][col]
        except IndexError:
            return ''

    def SetValue(self, row, col, value):
        try:
            self.data[row][col] = value
        except IndexError:
            # add a new row
            self.data.append([''] * self.GetNumberCols())
            self.SetValue(row, col, value)
            # tell the grid we've added a row
            msg = gridlib.GridTableMessage(self,            # The table
                    gridlib.GRIDTABLE_NOTIFY_ROWS_APPENDED, # what we did to it
                    1                                       # how many
                    )
            self.GetView().ProcessTableMessage(msg)

    # ---[ Some optional methods ] ---------------------------------------

    # Called when the grid needs to display labels
    def GetColLabelValue(self, col):
        return self.colLabels[col]

    # Called to determine the kind of editor/renderer to use by
    # default, doesn't necessarily have to be the same type used
    # natively by the editor/renderer if they know how to convert.
    def GetTypeName(self, row, col):
        return self.dataTypes[col]

    # Called to determine how the data can be fetched and stored by the
    # editor and renderer.  This allows you to enforce some type-safety
    # in the grid.
    def CanGetValueAs(self, row, col, typeName):
        colType = self.dataTypes[col].split(':')[0]
        if typeName == colType:
            return True
        else:
            return False

    def CanSetValueAs(self, row, col, typeName):
        return self.CanGetValueAs(row, col, typeName)

class CustTableGrid(gridlib.Grid):

    def __init__(self, parent,quote):
        gridlib.Grid.__init__(self, parent, -1)
        table = CustomDataTable(quote)
        # The second parameter means that the grid is to take ownership of the
        # table and will destroy it when done.  Otherwise you would need to keep
        # a reference to it and call it's Destroy method later.
        self.SetTable(table, True)
        self.SetRowLabelSize(0)
        self.SetMargins(0,0)
        self.AutoSizeColumns(False)
        gridlib.EVT_GRID_CELL_LEFT_DCLICK(self, self.OnLeftDClick)

    # I do this because I don't like the default behaviour of not starting the
    # cell editor on double clicks, but only a second click.
    def OnLeftDClick(self, evt):
        if self.CanEnableCellControl():
            self.EnableCellEditControl()

class iTradeQuoteTablePanel(wx.Panel):

    def __init__(self,parent,id,quote):
        wx.Panel.__init__(self, parent, id)
        self.m_id = id
        self.m_quote = quote
        self.m_parent = parent
        self.m_port = parent.portfolio()

        # create the grid
        self.m_grid = CustTableGrid(self,quote)

        # --- vertical sizer
        bs = wx.BoxSizer(wx.VERTICAL)
        bs.Add(self.m_grid, 1, wx.GROW|wx.ALL, 5)
        self.SetSizer(bs)

    #def paint(self):
    #    pass
    #
    #def refresh(self):
    #    info('QuoteTablePanel::refresh %s' % self.m_quote.ticker())
    #    self.paint()

    def DonePage(self):
        self.m_grid.Show(False)

    def InitPage(self):
        self.m_grid.Show(True)

# ============================================================================
# iTradeQuoteAnalysisPanel
#
#   Display Candlestick / Analysis on a specific quote
# ============================================================================

class iTradeQuoteAnalysisPanel(wx.Window):

    def __init__(self,parent,id,quote):
        wx.Window.__init__(self, parent, id)
        self.m_id = id
        self.m_quote = quote
        self.m_parent = parent
        self.m_port = parent.portfolio()

        txt = wx.StaticText(self, -1, "Candle : ", wx.Point(5,25), wx.Size(70, 20))
        self.m_candle = wx.StaticText(self, -1, "???", wx.Point(80,25), wx.Size(120, 20))

    #def paint(self):
    #    self.m_candle.SetLabel(self.m_quote.ov_candle().__str__())
    #
    #def refresh(self):
    #    info('QuoteAnalysisPanel::refresh %s' % self.m_quote.ticker())
    #    self.paint()

    def InitPage(self):
        self.m_candle.SetLabel(self.m_quote.ov_candle().__str__())

    def DonePage(self):
        pass

# ============================================================================
# iTradeQuoteLivePanel
#
# ============================================================================

class iTradeQuoteLivePanel(wx.Panel):

    def __init__(self,parent,gparent,id,quote):
        wx.Panel.__init__(self, parent, id)
        self.m_id = id
        self.m_quote = quote
        self.m_parent = gparent
        self.m_port = parent.portfolio()

        self.m_live = iTrade_wxLive(self,gparent,self.m_quote)
        self.m_decision = iTrade_wxDecision(self,self.m_quote,self.m_port)
        wx.EVT_SIZE(self,self.OnSize)

    def InitPage(self):
        self.m_live.InitPage()

    def DonePage(self):
        self.m_live.DonePage()

    def refresh(self):
        self.m_live.refresh()
        self.m_decision.refresh()

    def OnSize(self, event):
        w,h = self.GetClientSizeTuple()
        self.m_live.SetDimensions(0, 0, w, 180)
        self.m_decision.SetDimensions(0, 180, w, h-180)

# ============================================================================
# iTradeQuoteGraphPanel
# ============================================================================

class iTradeQuoteGraphPanel(wx.Panel,iTrade_wxPanelGraph):
    def __init__(self, parent, id, quote):
        wx.Panel.__init__(self, parent, id)
        iTrade_wxPanelGraph.__init__(self, parent, id, size=(5,4))

        self.m_id = id
        self.m_quote = quote
        self.m_nIndex = self.m_quote.lastindex()
        #print 'm_nIndex=',self.m_nIndex

        self.zoomPeriod = (20,40,80,160,320)
        self.zoomIncPeriod = (5,10,20,40,80)
        self.zoomWidth = (9,6,3,2,1)
        self.zoomMultiple = (2,5,10,20,40)
        self.zoomLevel = 2
        self.zoomMaxLevel = len(self.zoomPeriod)-1

        # settings
        self.m_dispMA150 = False
        self.m_dispBollinger = True
        self.m_dispOverlaidVolume = False
        self.m_dispLegend = True
        self.m_dispGrid = True
        self.m_dispChart1Type = 'c'
        self.m_dispRSI14 = True
        self.m_dispSto = False

        # parameter iTrade_wxPanelGraph
        self.m_hasChart1Vol = self.m_dispOverlaidVolume
        self.m_hasChart2Vol = True
        self.m_hasGrid = self.m_dispGrid
        self.m_hasLegend = self.m_dispLegend

    def InitPage(self):
        print '$$$InitPage'
        self.RedrawAll(redraw=False)

    def DonePage(self):
        print '$$$DonePage'
        pass

    def RedrawAll(self,redraw=True):
        print '$$$RedrawAll redraw=%s' % redraw
        self.ChartRealize()
        if redraw:
            self.m_canvas.draw()
            self.drawAllObjects()

    def OnPaint(self,event):
        self.erase_cursor()
        event.Skip()

    def refresh(self):
        print '$$$refresh'
        self.RedrawAll()

    def OnHome(self,event):
        self.m_nIndex = self.m_quote.lastindex()
        self.zoomLevel = 2
        self.removeAllObjects()
        self.RedrawAll()

    def OnPanLeft(self,event):
        min = self.m_quote.firstindex() + self.zoomPeriod[self.zoomLevel]
        if self.m_nIndex >= min:
            self.m_nIndex = self.m_nIndex - self.zoomIncPeriod[self.zoomLevel]
            if self.m_nIndex <= min:
                self.m_nIndex = min
            self.RedrawAll()

    def OnPanRight(self,event):
        if self.m_nIndex < self.m_quote.lastindex():
            self.m_nIndex = self.m_nIndex + self.zoomIncPeriod[self.zoomLevel]
            if self.m_nIndex >= self.m_quote.lastindex():
                self.m_nIndex = self.m_quote.lastindex()
            self.RedrawAll()

    def OnZoomOut(self,event):
        if self.zoomLevel < self.zoomMaxLevel:
            self.zoomLevel = self.zoomLevel + 1
            if self.zoomLevel > self.zoomMaxLevel:
                self.zoomLevel = self.zoomMaxLevel
            self.RedrawAll()

    def OnZoomIn(self,event):
        if self.zoomLevel > 0:
            self.zoomLevel = self.zoomLevel - 1
            if self.zoomLevel < 0:
                self.zoomLevel = 0
            self.RedrawAll()

    def OnConfig(self,event):
        if not hasattr(self, "m_popupID_dispMA150"):
            self.m_popupID_dispMA150 = wx.NewId()
            wx.EVT_MENU(self, self.m_popupID_dispMA150, self.OnPopup_dispMA150)
            self.m_popupID_dispRSI14 = wx.NewId()
            wx.EVT_MENU(self, self.m_popupID_dispRSI14, self.OnPopup_dispRSI14)
            self.m_popupID_dispSto = wx.NewId()
            wx.EVT_MENU(self, self.m_popupID_dispSto, self.OnPopup_dispSto)
            self.m_popupID_dispBollinger = wx.NewId()
            wx.EVT_MENU(self, self.m_popupID_dispBollinger, self.OnPopup_dispBollinger)
            self.m_popupID_dispOverlaidVolume = wx.NewId()
            wx.EVT_MENU(self, self.m_popupID_dispOverlaidVolume, self.OnPopup_dispOverlaidVolume)
            self.m_popupID_dispLegend = wx.NewId()
            wx.EVT_MENU(self, self.m_popupID_dispLegend, self.OnPopup_dispLegend)
            self.m_popupID_dispGrid = wx.NewId()
            wx.EVT_MENU(self, self.m_popupID_dispGrid, self.OnPopup_dispGrid)
            self.m_popupID_dispChart1Candlestick = wx.NewId()
            wx.EVT_MENU(self, self.m_popupID_dispChart1Candlestick, self.OnPopup_dispChart1Candlestick)
            self.m_popupID_dispChart1OHLC = wx.NewId()
            wx.EVT_MENU(self, self.m_popupID_dispChart1OHLC, self.OnPopup_dispChart1OHLC)
            self.m_popupID_dispChart1Line = wx.NewId()
            wx.EVT_MENU(self, self.m_popupID_dispChart1Line, self.OnPopup_dispChart1Line)

        # make a menu
        self.popmenu = wx.Menu()
        # add items
        i = self.popmenu.AppendRadioItem(self.m_popupID_dispChart1Candlestick, message('quote_popup_dispChart1Candlestick'))
        i.Check(self.m_dispChart1Type == 'c')
        i = self.popmenu.AppendRadioItem(self.m_popupID_dispChart1OHLC, message('quote_popup_dispChart1OHLC'))
        i.Check(self.m_dispChart1Type == 'o')
        i = self.popmenu.AppendRadioItem(self.m_popupID_dispChart1Line, message('quote_popup_dispChart1Line'))
        i.Check(self.m_dispChart1Type == 'l')
        self.popmenu.AppendSeparator()
        i = self.popmenu.AppendCheckItem(self.m_popupID_dispLegend, message('quote_popup_dispLegend'))
        i.Check(self.m_dispLegend)
        i = self.popmenu.AppendCheckItem(self.m_popupID_dispGrid, message('quote_popup_dispGrid'))
        i.Check(self.m_dispGrid)
        self.popmenu.AppendSeparator()
        i = self.popmenu.AppendCheckItem(self.m_popupID_dispMA150, message('quote_popup_dispMA150'))
        i.Check(self.m_dispMA150)
        i = self.popmenu.AppendCheckItem(self.m_popupID_dispSto, message('quote_popup_dispSto'))
        i.Check(self.m_dispSto)
        i = self.popmenu.AppendCheckItem(self.m_popupID_dispRSI14, message('quote_popup_dispRSI14'))
        i.Check(self.m_dispRSI14)
        i = self.popmenu.AppendCheckItem(self.m_popupID_dispBollinger, message('quote_popup_dispBollinger'))
        i.Check(self.m_dispBollinger)
        self.popmenu.AppendSeparator()
        i = self.popmenu.AppendCheckItem(self.m_popupID_dispOverlaidVolume, message('quote_popup_dispOverlaidVolume'))
        i.Check(self.m_dispOverlaidVolume)

        # Popup the menu.  If an item is selected then its handler
        # will be called before PopupMenu returns.
        self.m_toolbar.PopupMenu(self.popmenu, wx.Point(self.x, self.y))
        self.popmenu.Destroy()

    def OnPopup_dispChart1Candlestick(self,event):
        self.m_dispChart1Type = 'c'
        m = self.popmenu.FindItemById(self.m_popupID_dispChart1Candlestick)
        m.Check(True)
        self.RedrawAll()

    def OnPopup_dispChart1OHLC(self,event):
        self.m_dispChart1Type = 'o'
        m = self.popmenu.FindItemById(self.m_popupID_dispChart1OHLC)
        m.Check(True)
        self.RedrawAll()

    def OnPopup_dispChart1Line(self,event):
        self.m_dispChart1Type = 'l'
        m = self.popmenu.FindItemById(self.m_popupID_dispChart1Line)
        m.Check(True)
        self.RedrawAll()

    def OnPopup_dispGrid(self,event):
        self.m_dispGrid = not self.m_dispGrid
        m = self.popmenu.FindItemById(self.m_popupID_dispGrid)
        m.Check(self.m_dispGrid)
        self.m_hasGrid = self.m_dispGrid
        self.RedrawAll()

    def OnPopup_dispLegend(self,event):
        self.m_dispLegend = not self.m_dispLegend
        m = self.popmenu.FindItemById(self.m_popupID_dispLegend)
        m.Check(self.m_dispLegend)
        self.m_hasLegend = self.m_dispLegend
        self.RedrawAll()

    def OnPopup_dispSto(self,event):
        self.m_dispSto = not self.m_dispSto
        m = self.popmenu.FindItemById(self.m_popupID_dispSto)
        m.Check(self.m_dispSto)
        self.RedrawAll()

    def OnPopup_dispRSI14(self,event):
        self.m_dispRSI14 = not self.m_dispRSI14
        m = self.popmenu.FindItemById(self.m_popupID_dispRSI14)
        m.Check(self.m_dispRSI14)
        self.RedrawAll()

    def OnPopup_dispMA150(self,event):
        self.m_dispMA150 = not self.m_dispMA150
        m = self.popmenu.FindItemById(self.m_popupID_dispMA150)
        m.Check(self.m_dispMA150)
        self.RedrawAll()

    def OnPopup_dispBollinger(self,event):
        self.m_dispBollinger = not self.m_dispBollinger
        m = self.popmenu.FindItemById(self.m_popupID_dispBollinger)
        m.Check(self.m_dispBollinger)
        self.RedrawAll()

    def OnPopup_dispOverlaidVolume(self,event):
        self.m_dispOverlaidVolume = not self.m_dispOverlaidVolume
        m = self.popmenu.FindItemById(self.m_popupID_dispOverlaidVolume)
        m.Check(self.m_dispOverlaidVolume)
        self.m_hasChart1Vol = self.m_dispOverlaidVolume
        self.RedrawAll()

    def getPeriod(self):
        return self.zoomPeriod[self.zoomLevel]

    def getMultiple(self):
        return self.zoomMultiple[self.zoomLevel]

    def getTextPeriod(self):
        return '%s %s %s' % (message('graph_period'),self.getPeriod(),message('graph_days'))

    def ChartRealize(self):
        if self.m_dispRSI14 or self.m_dispSto:
            nchart = 3
        else:
            nchart = 2
        self.BeginCharting(nchart)

        end = self.m_nIndex + 1
        begin = end - self.zoomPeriod[self.zoomLevel]
        min = self.m_quote.firstindex()
        if begin<min:
            begin = min

        self.times = []
        self.idx = []
        num = 0

        for i in range(begin,end):
            if self.m_quote.m_daytrades.has_trade(i): num = num + 1
            dt = gCal.date(i)
            if dt:
                d = date2num(dt)
                self.times.append(d)
                self.idx.append(i)
                if self.m_dispRSI14:
                    self.m_quote.m_daytrades.rsi14(i)
                if self.m_dispSto:
                    self.m_quote.m_daytrades.stoK(i)
                    self.m_quote.m_daytrades.stoD(i)
                self.m_quote.m_daytrades.ma(20,i)
                self.m_quote.m_daytrades.ma(50,i)
                self.m_quote.m_daytrades.ma(100,i)
                if self.m_dispMA150:
                    self.m_quote.m_daytrades.ma(150,i)
                self.m_quote.m_daytrades.vma(15,i)
                self.m_quote.m_daytrades.ovb(i)
                if self.m_dispBollinger:
                    self.m_quote.m_daytrades.bollinger(i,0)

        # self.m_quote.m_daytrades.m_[begin:end]
        # print 'ChartRealize: begin:',begin,' end:',end,' num:',num

        if num>0:

            if self.m_dispChart1Type == 'c':
                lc = candlestick2(self.chart1, self.m_quote.m_daytrades.m_inOpen[begin:end], self.m_quote.m_daytrades.m_inClose[begin:end], self.m_quote.m_daytrades.m_inHigh[begin:end], self.m_quote.m_daytrades.m_inLow[begin:end], width = self.zoomWidth[self.zoomLevel], colorup = 'g', colordown = 'r', alpha=1.0)
            elif self.m_dispChart1Type == 'l':
                lc = plot_day_summary3(self.chart1, self.m_quote.m_daytrades.m_inClose[begin:end], ticksize=self.zoomWidth[self.zoomLevel], color='k')
            elif self.m_dispChart1Type == 'o':
                lc = plot_day_summary2(self.chart1, self.m_quote.m_daytrades.m_inOpen[begin:end], self.m_quote.m_daytrades.m_inClose[begin:end], self.m_quote.m_daytrades.m_inHigh[begin:end], self.m_quote.m_daytrades.m_inLow[begin:end], ticksize=self.zoomWidth[self.zoomLevel], colorup='k', colordown='r')
            else:
                lc = None

            if not self.m_dispBollinger:
                lma20 = self.chart1.plot(self.m_quote.m_daytrades.m_ma20[begin:end],'m')
            lma50 = self.chart1.plot(self.m_quote.m_daytrades.m_ma50[begin:end],'r')
            lma100 = self.chart1.plot(self.m_quote.m_daytrades.m_ma100[begin:end],'b')
            if self.m_dispMA150:
                lma150 = self.chart1.plot(self.m_quote.m_daytrades.m_ma150[begin:end],'c')

            if self.m_dispBollinger:
                lma20 = self.chart1.plot(self.m_quote.m_daytrades.m_bollM[begin:end],'m--')
                lu = self.chart1.plot(self.m_quote.m_daytrades.m_bollUp[begin:end],'k')
                ld = self.chart1.plot(self.m_quote.m_daytrades.m_bollDn[begin:end],'k')

            if self.m_dispOverlaidVolume:
                volume_overlay2(self.chart1vol, self.m_quote.m_daytrades.m_inClose[begin-1:end], self.m_quote.m_daytrades.m_inVol[begin-1:end], colorup='g', colordown='r', width=self.zoomWidth[self.zoomLevel]+1,alpha=0.5)
            #l5 = self.chart1vol.plot(self.m_quote.m_daytrades.m_ovb[begin:end],'k')

            volume_overlay2(self.chart2, self.m_quote.m_daytrades.m_inClose[begin-1:end], self.m_quote.m_daytrades.m_inVol[begin-1:end], colorup='g', colordown='r', width=self.zoomWidth[self.zoomLevel]+1,alpha=1.0)
            lvma15 = self.chart2.plot(self.m_quote.m_daytrades.m_vma15[begin:end],'r',antialiased=False,linewidth=0.05)
            lovb = self.chart2vol.plot(self.m_quote.m_daytrades.m_ovb[begin:end],'k',antialiased=False,linewidth=0.05)
            #index_bar(self.chart2, self.m_quote.m_daytrades.m_inVol[begin:end], facecolor='g', edgecolor='k', width=4,alpha=1.0)

            if self.m_dispRSI14:
                rsi14 = self.chart3.plot(self.m_quote.m_daytrades.m_rsi14[begin:end],'k',antialiased=False,linewidth=0.05)
            else:
                rsi14 = None

            if self.m_dispSto:
                stoK = self.chart3.plot(self.m_quote.m_daytrades.m_stoK[begin:end],'b',antialiased=False,linewidth=0.05)
                stoD = self.chart3.plot(self.m_quote.m_daytrades.m_stoD[begin:end],'m--',antialiased=False,linewidth=0.05)
            else:
                stoK = None
                stoD = None

            if self.m_dispLegend:
                old = matplotlib.rcParams['lines.antialiased']
                matplotlib.rcParams['lines.antialiased']=False

                if self.m_dispMA150:
                    self.legend1 = self.chart1.legend((lma20, lma50, lma100, lma150), ('MMA(20)','MMA(50)','MMA(100)','MMA(150)'), loc=2, numpoints=2, pad=0.3, axespad=0.025) #'upper left'
                else:
                    self.legend1 = self.chart1.legend((lma20, lma50, lma100), ('MMA(20)','MMA(50)','MMA(100)'), loc=2, numpoints=2, pad=0.3, axespad=0.025) #'upper left'

                self.legend2 = self.chart2.legend((lvma15, lovb), ('VMA(15)', 'OVB'), loc=2, numpoints=2, pad=0.3, axespad=0.025) #'upper left'

                if self.m_dispRSI14:
                    if self.m_dispSto:
                        ll1 = (rsi14,stoK,stoD)
                        ll2 = ('RSI(14)','Sto %K','Sto %D')
                    else:
                        ll1 = (rsi14,)
                        ll2 = ('RSI(14)',)
                else:
                    if self.m_dispSto:
                        ll1 = (stoK,stoD)
                        ll2 = ('Sto %K','Sto %D')
                    else:
                        ll1 = None
                        ll2 = None
                if ll1:
                    self.legend3 = self.chart3.legend(ll1, ll2, loc=2, numpoints=2, pad=0.3, axespad=0.025) #'upper left'

                matplotlib.rcParams['lines.antialiased']=old

            left, top = 0.005, 1.005
            t = self.chart1.text(left, top, self.GetPeriod(1), fontsize = 7, transform = self.chart1.transAxes)

            left, top = 0.450, 1.005
            t = self.chart1.text(left, top, self.getTextPeriod(), fontsize = 7, transform = self.chart1.transAxes)

            left, top = 0.950, 1.005
            t = self.chart1.text(left, top, self.GetPeriod(-1), fontsize = 7, transform = self.chart1.transAxes)

        if self.m_quote.isTraded():
            self.chartUPL(self.m_quote.nv_pru())

        self.EndCharting()

    def GetPeriod(self,idxtime):
        dt = self.GetTime(idxtime)
        return dt.strftime(' %Y ')

    def GetXLabel(self,idxtime):
        dt = self.GetTime(idxtime)
        return dt.strftime(' %x ')

    def GetTime(self,idxtime):
        return gCal.date(self.GetIndexTime(idxtime))

    def GetIndexTime(self,idxtime):
        if idxtime<0:
            idxtime = len(self.idx)+idxtime
        elif idxtime==0:
            idxtime = len(self.idx)/2
        elif idxtime>=len(self.idx):
            idxtime = len(self.idx)-1
        return self.idx[idxtime]

    def GetYLabel(self,ax,value):
        if ax==self.chart1:
            return ' %.2f ' % value
        elif self.m_hasChart1Vol and (ax==self.chart1vol):
            return ' %s ' % fmtVolumeFunc(value,1)
        elif ax==self.chart2:
            return ' %s ' % fmtVolumeFunc(value,1)
        elif self.m_hasChart2Vol and (ax==self.chart2vol):
            return ' %s ' % fmtVolumeFunc(value,1)
        elif ax==self.chart3:
            return ' %.2f%% ' % value
        else:
           return ' unknown axis '

#"Time: %f\n Price:%f\nYOUPIE" %

    def space(self,msg,val):
        l = len(msg)
        m = max(22,len(self.m_quote.name()))
        while (l+len(val))<m:
            val = ' ' + val
        return msg+val

    def GetXYLabel(self,ax,data):
        idx = self.idx[data[0]]
        dt = gCal.date(idx)
        chart = self.axe2chart(ax)
        if self.m_quote.m_daytrades.has_trade(idx):
            s = 'k, ' + self.m_quote.name() + ' ('+ dt.strftime('%x') + ') \n'
            s = s + 'k, '+ self.space(message('popup_open'), self.m_quote.sv_open(dt)) + ' \n'
            s = s + 'k, '+ self.space(message('popup_high'), self.m_quote.sv_high(dt)) + ' \n'
            s = s + 'k, '+ self.space(message('popup_low'), self.m_quote.sv_low(dt)) + ' \n'
            s = s + 'k, '+ self.space(message('popup_close'), self.m_quote.sv_close(dt)) + ' \n'
            s = s + 'k, '+ self.space(message('popup_percent') % self.m_quote.sv_percent(dt), self.m_quote.sv_unitvar(dt)) + ' \n'
            s = s + 'k, '+ self.space(message('popup_volume') , self.m_quote.sv_volume(dt)) + ' \n'
            if chart==3:
                if self.m_dispRSI14:
                    s = s + 'k, '+ self.space('RSI (%s)'%14, self.m_quote.sv_rsi(14,dt)) + ' \n'
                if self.m_dispSto:
                    s = s + 'b, '+ self.space('STO %%K (%s)'%14, self.m_quote.sv_stoK(dt)) + ' \n'
                    s = s + 'm, '+ self.space('STO %%D (%s)'%14, self.m_quote.sv_stoD(dt)) + ' \n'
            elif chart==2:
                s = s + 'r, '+ self.space('VMA%s'%15, self.m_quote.sv_vma(15,dt)) + ' \n'
                s = s + 'k, '+ self.space('OVB', self.m_quote.sv_ovb(dt)) + ' \n'
            else:
                s = s + 'm, '+ self.space('MA%s'%20, self.m_quote.sv_ma(20,dt)) + ' \n'
                s = s + 'r, '+ self.space('MA%s'%50, self.m_quote.sv_ma(50,dt)) + ' \n'
                s = s + 'b, '+ self.space('MA%s'%100, self.m_quote.sv_ma(100,dt)) + ' \n'
                if self.m_dispMA150:
                    s = s + 'c, '+ self.space('MA%s'%150, self.m_quote.sv_ma(150,dt)) + ' \n'
        else:
            s = 'k, ' + self.m_quote.name() + ' ('+ dt.strftime('%x') + ') \n'
            s = s + 'k, ' + message('popup_notrade') + ' '

        return s

# ============================================================================
# iTradeQuoteNotebookWindow
#
#   Display Notebook on a specific quote
# ============================================================================

class iTradeQuoteNotebookWindow(wx.Notebook):

    ID_PAGE_GRAPH = 0
    ID_PAGE_LIVE = 1
    ID_PAGE_INTRADAY = 2
    ID_PAGE_NEWS = 3
    ID_PAGE_ANALYSIS = 4
    ID_PAGE_TABLE = 5
    ID_PAGE_PROP = 6

    def __init__(self,parent,id,size,quote,page=0):
        wx.Notebook.__init__(self,parent,id,wx.DefaultPosition, size, style=wx.SIMPLE_BORDER|wx.NB_TOP)
        self.m_quote = None
        self.m_parent = parent
        self.m_port = parent.portfolio()
        self.m_curpage = page
        page = self.init(quote,page,fromInit=True)
        wx.EVT_NOTEBOOK_PAGE_CHANGED(self, self.GetId(), self.OnPageChanged)
        wx.EVT_NOTEBOOK_PAGE_CHANGING(self, self.GetId(), self.OnPageChanging)
        self.SetSelection(page)

    def portfolio(self):
        return self.m_port

    def OnPageChanged(self, event):
        old = event.GetOldSelection()
        new = event.GetSelection()
        sel = self.GetSelection()
        if itrade_config.verbose:
            print
            print 'QuoteNotebookWindow::OnPageChanged: old=%d new=%d sel=%d' % (old, new, sel)
        if old<>new:
            if old>=0:
                self.win[old].DonePage()
            if new>=0:
                self.m_curpage = new
                self.win[new].InitPage()
        event.Skip()

    def OnPageChanging(self, event):
        # not used - only for traces
        if 0:
            old = event.GetOldSelection()
            new = event.GetSelection()
            sel = self.GetSelection()
            if itrade_config.verbose:
                print 'QuoteNotebookWindow::OnPageChanging: old=%d new=%d sel=%d' % (old, new, sel)
        event.Skip()

    def init(self,nquote=None,page=0,fromInit=False):
        # check new quote
        if nquote<>self.m_quote:
            self.m_quote = nquote

            # regenerate pages with the new quote
            self.win = {}
            self.DeleteAllPages()

            self.win[self.ID_PAGE_GRAPH] = iTradeQuoteGraphPanel(self,wx.NewId(),self.m_quote)
            self.AddPage(self.win[self.ID_PAGE_GRAPH], message('quote_graphdaily'))

            self.win[self.ID_PAGE_LIVE] = iTradeQuoteLivePanel(self,self.m_parent,wx.NewId(),self.m_quote)
            self.AddPage(self.win[self.ID_PAGE_LIVE], message('quote_live'))

            # found the right URL for intraday charting
            m = self.m_quote.market()
            if not itrade_config.intradayGraphUrl.has_key(m):
                m = m+"."+self.m_quote.place()
                if not itrade_config.intradayGraphUrl.has_key(m):
                    m = None
            if m:
                url = itrade_config.intradayGraphUrl[m]
                isin = itrade_config.intradayGraphUrlUseISIN[m]

                if isin:
                    url = url % self.m_quote.isin()
                else:
                    url = url % self.m_quote.ticker()
            else:
                # chart not available because no url
                url = ''

            self.win[self.ID_PAGE_INTRADAY] = iTradeHtmlPanel(self,wx.NewId(), url)
            self.AddPage(self.win[self.ID_PAGE_INTRADAY], message('quote_intraday'))

            self.win[self.ID_PAGE_NEWS] = iTradeRSSPanel(self,wx.NewId(),self.m_quote)
            self.AddPage(self.win[self.ID_PAGE_NEWS], message('quote_news'))

            self.win[self.ID_PAGE_ANALYSIS] = iTradeQuoteAnalysisPanel(self,wx.NewId(),self.m_quote)
            self.AddPage(self.win[self.ID_PAGE_ANALYSIS], message('quote_analysis'))

            self.win[self.ID_PAGE_TABLE] = iTradeQuoteTablePanel(self,wx.NewId(),self.m_quote)
            self.AddPage(self.win[self.ID_PAGE_TABLE], message('quote_table'))

            self.win[self.ID_PAGE_PROP] = iTradeQuotePropertiesPanel(self,wx.NewId(),self.m_quote)
            self.AddPage(self.win[self.ID_PAGE_PROP], message('quote_properties'))

            # be sure to init & display the selected page
            if fromInit: self.win[page].InitPage()

            return page

    def refresh(self,nquote=None,live=False):
        if nquote:
            # refresh the new quote
            if itrade_config.verbose:
                print 'QuoteNotebookWindow::refresh Init New Quote : %s - page: %d' % (nquote.ticker(),self.m_curpage)
            page = self.init(nquote,self.m_curpage)
            if itrade_config.verbose:
                print 'QuoteNotebookWindow::refresh Internal Page : %s - page: %d' % (nquote.ticker(),page)
            self.SetSelection(page)
        else:
            # refresh current page
            if (self.m_curpage==self.ID_PAGE_LIVE) or (not live):
                if itrade_config.verbose:
                    print 'QuoteNotebookWindow::refresh Current Quote %s live=%s page: %d' % (self.m_quote.ticker(),live,self.m_curpage)
                self.win[self.m_curpage].refresh()

# ============================================================================
# iTradeQuoteWindow
#
# Container to display information and panels on a specific quote
# ============================================================================

class iTradeQuoteWindow(wx.Frame,iTrade_wxFrame,iTrade_wxLiveMixin):

    def __init__(self,parent,id,port,quote,dpage=0):
        self.m_id = wx.NewId()

        # init mixins
        wx.Frame.__init__(self,None,self.m_id, size = ( 800,480), style = wx.DEFAULT_FRAME_STYLE | wx.NO_FULL_REPAINT_ON_RESIZE)
        iTrade_wxFrame.__init__(self,parent,'view',hasStatusBar=False)
        iTrade_wxLiveMixin.__init__(self)

        # store linked information
        self.m_quote = quote
        self.m_parent = parent
        self.m_port = port

        # register live mechanism (-> OnLive handler must be implemented)
        self.registerLive(quote,itrade_config.refreshLive)

        # fix title
        self.setTitle()

        # info + panels
        self.m_infowindow = iTradeQuoteInfoWindow(self, -1, size=wx.DefaultSize ,quote=self.m_quote)
        self.m_notewindow = iTradeQuoteNotebookWindow(self, -1, size=wx.DefaultSize ,quote=self.m_quote, page=dpage)

        # handlers
        wx.EVT_WINDOW_DESTROY(self, self.OnDestroy)
        wx.EVT_SIZE(self, self.OnSize)
        EVT_UPDATE_LIVE(self, self.OnLive)

    # ---[ Linked information accessors ] -------------------------------------

    def portfolio(self):
        return self.m_port

    def parent(self):
        return self.m_parent

    def quote(self):
        return self.m_quote

    # ---[ Change the current window title ] ----------------------------------

    def setTitle(self):
        self.SetTitle("%s %s - %s : %s" % (message('quote_title'),self.m_quote.key(),self.m_quote.ticker(),self.m_quote.name()))

    # ---[ Select a new quote ] -----------------------------------------------

    def SelectQuote(self,nquote=None):
        if not nquote:
            nquote = select_iTradeQuote(self,self.m_quote,filter=True,market=None)
        if nquote and nquote<>self.m_quote:
            if itrade_config.verbose:
                print
                print 'QuoteWindow::SelectQuote: %s -> %s %s' % (self.m_quote.ticker(),nquote.ticker(),nquote.key())
            self.stopLive(self.m_quote)
            self.unregisterLive(self.m_quote)
            self.m_notewindow.Hide()
            self.m_quote = nquote
            self.registerLive(self.m_quote,itrade_config.refreshLive)
            self.setTitle()
            self.refresh(self.m_quote)
            self.m_notewindow.Show()

    # ---[ Refresh mechanism ] ------------------------------------------------

    def refresh(self,nquote=None,live=False):
        if itrade_config.verbose:
            print'QuoteWindow::refresh %s %s: live=%s' % (self.m_quote.ticker(),self.m_quote.key(),live)
        self.m_infowindow.refresh(nquote,live)
        self.m_notewindow.refresh(nquote,live)

    def OnLive(self, evt):
        # be sure this quote is still under population
        if evt.quote == self.m_quote and self.isRunning(evt.quote):
            if itrade_config.verbose:
                print 'QuoteWindow::OnLive %s %s: %s' % (evt.quote.ticker(),evt.quote.key(),evt.param)
            self.refresh(live=True)
        else:
            if itrade_config.verbose:
                print 'QuoteWindow::OnLive %s %s: %s - NOT RUNNING' % (evt.quote.ticker(),evt.quote.key(),evt.param)

    # ---[ Default Windows handlers ] -----------------------------------------

    # Default OnSize handler
    def OnSize(self, event):
        w,h = self.GetClientSizeTuple()
        self.m_infowindow.SetDimensions(0, 0, 129, h)
        self.m_notewindow.SetDimensions(130, 0, w-130, h)
        event.Skip()

    # Default OnDestroy handler
    def OnDestroy(self, evt):
        if self.m_id == evt.GetId():
            # stop & unregister live
            self.stopLive(self.m_quote)
            self.unregisterLive(self.m_quote)

            # remove view from the parent stack
            if self.m_parent:
                self.m_parent.m_hView = None

    # Default OnExit handler
    def OnExit(self, evt):
        # save any configuration
        self.saveConfig()

        # close the view
        self.Close()

# ============================================================================
# open_iTradeQuote
#
#   win     parent window
#   quote   Quote object or ISIN reference to view
#   page    page to select
# ============================================================================

def open_iTradeQuote(win,port,quote,page=0):
    if not isinstance(quote,Quote):
        quote = quotes.lookupKey(quote)
    if win and win.m_hView:
        # set focus
        win.m_hView.SelectQuote(quote)
        win.m_hView.SetFocus()
    else:
        frame = iTradeQuoteWindow(win, -1,port,quote,page)
        if win:
            win.m_hView = frame
        # __w frame.plot_data()
        frame.Show()

# ============================================================================
# addInMatrix_iTradeQuote
#
#   win         parent window
#   matrix      Matrix object
#   portfolio   Portfolio object
#   dquote      (optional) Quote object or ISIN reference
# ============================================================================

def addInMatrix_iTradeQuote(win,matrix,portfolio,dquote=None):
    if dquote:
        if not isinstance(dquote,Quote):
            dquote = quotes.lookupKey(dquote)
    else:
        dquote = select_iTradeQuote(win,dquote=None,filter=False,market=portfolio.market())

    if dquote:
        matrix.addKey(dquote.key())
        return dquote
    return None

# ============================================================================
# removeFromMatrix_iTradeQuote
#
#   win     parent window
#   matrix  Matrix object
#   quote   Quote object or ISIN reference
# ============================================================================

def removeFromMatrix_iTradeQuote(win,matrix,quote):
    if not isinstance(quote,Quote):
        quote = quotes.lookupKey(quote)
    if quote:
        if not quote.isTraded():
            matrix.removeKey(quote.key())
            return True
    return False

# ============================================================================
# Test me
# ============================================================================

if __name__=='__main__':
    setLevel(logging.INFO)

    app = wx.PySimpleApp()

    # load configuration
    import itrade_config
    itrade_config.loadConfig()

    from itrade_local import *
    setLang('us')
    gMessage.load()

    # load extensions
    import itrade_ext
    itrade_ext.loadExtensions(itrade_config.fileExtData,itrade_config.dirExtData)

    # init modules
    initQuotesModule()

    itrade_config.verbose = False

    from itrade_portfolio import *
    initPortfolioModule()

    port = loadPortfolio('default')

    q = quotes.lookupTicker('SAF','EURONEXT')
    if q:
        open_iTradeQuote(None,port,q)
        app.MainLoop()

# ============================================================================
# That's all folks !
# ============================================================================
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.