[profitpy commit] r321 - in trunk: . profit/models profit/session profit/workbench profit/workbench/widgets

2 views
Skip to first unread message

codesite...@google.com

unread,
Aug 2, 2008, 6:21:13 PM8/2/08
to profitp...@googlegroups.com
Author: troy.melhase
Date: Sat Aug 2 15:20:12 2008
New Revision: 321

Added:
trunk/profit/models/portfolio.py (contents, props changed)
Modified:
trunk/README
trunk/profit/models/orders.py
trunk/profit/session/__init__.py
trunk/profit/workbench/centraltabs.py
trunk/profit/workbench/portfoliodisplay.py
trunk/profit/workbench/sessiontree.py
trunk/profit/workbench/widgets/ui_portfoliodisplay.ui

Log:
Added abstract portfolio model and adjusted portfolio display to use it.

Modified: trunk/README
==============================================================================
--- trunk/README (original)
+++ trunk/README Sat Aug 2 15:20:12 2008
@@ -56,10 +56,10 @@
> adds message index to local list (called "messageIndexes")
ExecutionsDisplay

+
orderdisplay.py
OrderDisplay(QFrame)
- on_session_OrderStatus -> updates self.orderTable
- on_session_OpenOrder -> updates self.orderTable
+ orderView -> session.models.orders


plotdatadialog.py

Modified: trunk/profit/models/orders.py
==============================================================================
--- trunk/profit/models/orders.py (original)
+++ trunk/profit/models/orders.py Sat Aug 2 15:20:12 2008
@@ -28,15 +28,16 @@
return QVariant()
item = index.internalPointer()
data = QVariant()
- if (role == Qt.DecorationRole and index.column() == 1):
+ column = index.column()
+ if (role == Qt.DecorationRole and column == 1):
data = QVariant(self.symbolIcon(item.symbol()))
elif role in (Qt.DisplayRole, Qt.ToolTipRole):
- data = QVariant(item[index.column()])
+ data = QVariant(item[column])
elif role in (Qt.TextAlignmentRole, ):
try:
- float(item[index.column()])
+ float(item[column])
data = QVariant(valueAlign)
- except:
+ except (ValueError, TypeError, ):
pass
return data


Added: trunk/profit/models/portfolio.py
==============================================================================
--- (empty file)
+++ trunk/profit/models/portfolio.py Sat Aug 2 15:20:12 2008
@@ -0,0 +1,150 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# Copyright 2007 Troy Melhase <tr...@gci.net>
+# Distributed under the terms of the GNU General Public License v2
+
+from PyQt4.QtCore import Qt, QModelIndex, QVariant, QString
+from profit.lib import valueAlign
+from profit.models import BasicItem, BasicItemModel
+
+
+class PortfolioModel(BasicItemModel):
+ """
+
+ """
+ def __init__(self, session=None, parent=None):
+ BasicItemModel.__init__(self, RootPortfolioItem(), parent)
+ self.symbolIcon = lambda x:None
+ self.session = session
+ if session is not None:
+ session.registerMeta(self)
+
+ def data(self, index, role):
+ """
+
+ """
+ if not index.isValid():
+ return QVariant()
+ item = index.internalPointer()
+ data = QVariant()
+ column = index.column()
+ amChild = index.parent().isValid()
+ if role == Qt.DecorationRole and column==0:
+ if not amChild:
+ data = QVariant(self.symbolIcon(item.symbol()))
+ elif role in (Qt.DisplayRole, Qt.ToolTipRole):
+ if amChild and (column==0):
+ data = QVariant(item.row())
+ else:
+ data = QVariant(item[column])
+ elif role in (Qt.TextAlignmentRole, ):
+ try:
+ float(item[column])
+ data = QVariant(valueAlign)
+ except (ValueError, ):
+ pass
+ return data
+
+ def findPortfolioItem(self, contract):
+ """ Returns the item for the given contract, or None.
+
+ """
+ items = self.invisibleRootItem.children
+ try:
+ return [i for i in items if i.message.contract==contract][0]
+ except (IndexError, ):
+ pass
+
+ def on_session_UpdatePortfolio(self, message):
+ """ Adds a status row if the contract is known to the model.
+
+ """
+ contract = message.contract
+ item = self.findPortfolioItem(contract)
+ if not item:
+ root = self.invisibleRootItem
+ item = PortfolioItem.fromMessage(message, root)
+ root.append(item)
+ item.append(UpdatePortfolioItem.fromMessage(message, item))
+ item.update(message)
+ self.reset()
+
+
+class PortfolioItem(BasicItem):
+ """ Base class for items in the portfolio model.
+
+ """
+ columnLookups = [
+ ('Symbol', lambda x:x.contract.m_symbol),
+ ('Position', lambda x:x.position),
+ ('Market Price', lambda x:x.marketPrice),
+ ('Market Value', lambda x:x.marketValue),
+ ('Average Cost', lambda x:x.averageCost),
+ ('Unrealized Profit', lambda x:x.unrealizedPNL),
+ ('Realized Profit', lambda x:x.realizedPNL),
+ ('Account', lambda x:x.accountName),
+ ]
+
+ def __init__(self, data, parent=None, message=None):
+ BasicItem.__init__(self, data, parent)
+ self.message = message
+
+ @classmethod
+ def fromMessage(cls, message, parent):
+ """ New instance from message values
+
+ @param cls class object
+ @param message ib.opt.message object
+ @param parent parent of this item
+ @return new instance of cls
+ """
+ values = []
+ for label, lookup in cls.columnLookups:
+ try:
+ value = lookup(message)
+ except (AttributeError, ):
+ value = ''
+ values.append(value)
+ return cls(values, parent, message)
+
+ def symbol(self):
+ """ Returns the symbol for this item or ''
+
+ """
+ try:
+ return self.message.contract.m_symbol
+ except (AttributeError, ):
+ return ''
+
+ def update(self, message):
+ """ Update the item with values from a message.
+
+ @param message ib.opt.message object
+ @return None
+ """
+ for column, (label, lookup) in enumerate(self.columnLookups):
+ try:
+ self[column] = lookup(message)
+ except (AttributeError, ):
+ pass
+
+
+class RootPortfolioItem(PortfolioItem):
+ """ Portfolio model item with automatic values (for horizontal headers).
+
+ """
+ def __init__(self):
+ PortfolioItem.__init__(self, self.horizontalLabels())
+
+ def horizontalLabels(self):
+ """ Generates list of horizontal header values.
+
+ """
+ return map(QVariant, [label for label, lookup in self.columnLookups])
+
+
+class UpdatePortfolioItem(PortfolioItem):
+ """ Specialized status item; empty for now.
+
+ """

Modified: trunk/profit/session/__init__.py
==============================================================================
--- trunk/profit/session/__init__.py (original)
+++ trunk/profit/session/__init__.py Sat Aug 2 15:20:12 2008
@@ -23,6 +23,7 @@
from profit.strategy.builder import SessionStrategyBuilder

from profit.models.orders import OrdersModel
+from profit.models.portfolio import PortfolioModel


class DataMaps(object):
@@ -38,7 +39,7 @@
class DataModels(object):
def __init__(self, session):
self.orders = OrdersModel(session)
-
+ self.portfolio = PortfolioModel(session)

class Session(QObject):
""" This is the big-honkin Session class.

Modified: trunk/profit/workbench/centraltabs.py
==============================================================================
--- trunk/profit/workbench/centraltabs.py (original)
+++ trunk/profit/workbench/centraltabs.py Sat Aug 2 15:20:12 2008
@@ -15,8 +15,6 @@
from profit.lib import BasicHandler, Signals, DataRoles, instance
from profit.lib.gui import addCloseAction, makeUrlItem
from profit.lib.widgets.buttons import CloseTabButton, DetachTabButton
-from profit.lib.widgets.webbrowser import WebBrowserDisplay
-from profit.workbench.tickerplotdisplay import TickerPlotDisplay


class CentralTabs(QTabWidget, BasicHandler):
@@ -65,6 +63,7 @@
@param value string or model item
@return True if display widget created, otherwise None
"""
+ from profit.lib.widgets.webbrowser import WebBrowserDisplay
if isinstance(item, (basestring, )):
item = makeUrlItem(item)
if item.data(DataRoles.url).isValid():
@@ -87,6 +86,7 @@
@param value string or model item
@return True if display widget created, otherwise None
"""
+ from profit.workbench.tickerplotdisplay import TickerPlotDisplay
tickerId, tickerIdValid = item.data(DataRoles.tickerId).toInt()
symbol = str(item.data(DataRoles.tickerSymbol).toString())
if tickerIdValid and self.setCurrentLabel(symbol):

Modified: trunk/profit/workbench/portfoliodisplay.py
==============================================================================
--- trunk/profit/workbench/portfoliodisplay.py (original)
+++ trunk/profit/workbench/portfoliodisplay.py Sat Aug 2 15:20:12 2008
@@ -4,59 +4,44 @@
# Copyright 2007 Troy Melhase <tr...@gci.net>
# Distributed under the terms of the GNU General Public License v2

-from itertools import ifilter
+from PyQt4.QtGui import QFrame

-from PyQt4.QtCore import Qt
-from PyQt4.QtGui import QFrame, QIcon
-
-from profit.lib import BasicHandler, makeCheckNames
-from profit.lib.gui import ValueTableItem
+from profit.lib import BasicHandler, Signals
+from profit.lib.gui import symbolIcon
from profit.workbench.widgets.ui_portfoliodisplay import Ui_PortfolioDisplay


-def replayPortfolio(messages, callback):
- isPortMessage = makeCheckNames('UpdatePortfolio')
- symbols = (m.contract.m_symbol for t, m in messages if isPortMessage(m))
- for symbol in set(symbols):
- def pred((t, m)):
- return isPortMessage(m) and m.contract.m_symbol==symbol
- for time, message in ifilter(pred, reversed(messages)):
- callback(message)
- break
-
-
class PortfolioDisplay(QFrame, Ui_PortfolioDisplay, BasicHandler):
+ """ PortfolioDisplay -> display the portfolio messages
+
+ """
def __init__(self, parent=None):
+ """ Initializer.
+
+ @param parent ancestor of this object
+ """
QFrame.__init__(self, parent)
self.setupUi(self)
- self.portfolioItems = {}
- self.portfolioTable.verticalHeader().hide()
self.requestSession()

def setSession(self, session):
- self.session = session
- replayPortfolio(session.messages, self.on_session_UpdatePortfolio)
- session.registerMeta(self)
+ """ Configures this instance for a session.

- def on_session_UpdatePortfolio(self, message):
- sym = message.contract.m_symbol
- table = self.portfolioTable
- try:
- items = self.portfolioItems[sym]
- except (KeyError, ):
- items = self.portfolioItems[sym] = table.newItemsRow()
- items[0].setSymbol(sym)
- for item in items[1:]:
- item.setValueAlign()
- table.resizeColumnToContents(0)
- table.resizeRowsToContents()
- items[1].setValue(message.position)
- items[2].setValue(message.marketPrice)
- items[3].setValue(message.marketValue)
- items[4].setValue(message.averageCost)
- items[5].setValue(message.unrealizedPNL)
- items[6].setValue(message.realizedPNL)
- items[7].setText(message.accountName)
- for col in range(table.columnCount()):
- table.resizeColumnToContents(col)
+ @param session Session instance
+ @return None
+ """
+ self.session = session
+ model = session.models.portfolio
+ model.symbolIcon = symbolIcon
+ self.connect(model, Signals.modelReset, self.resizeTree)
+ self.portfolioView.setModel(model)
+
+ def resizeTree(self):
+ """ Resizes all columns in the portfolio tree.
+
+ """
+ view = self.portfolioView
+ cols = range(view.model().invisibleRootItem.itemCount())
+ for col in cols:
+ view.resizeColumnToContents(col)


Modified: trunk/profit/workbench/sessiontree.py
==============================================================================
--- trunk/profit/workbench/sessiontree.py (original)
+++ trunk/profit/workbench/sessiontree.py Sat Aug 2 15:20:12 2008
@@ -297,8 +297,8 @@
tabstate = settings.valueLoad(settings.keys.ctabstate, [])
settings.endGroup()
connection = 'connection'
- if connection not in tabstate:
- tabstate.append(connection)
+ #if connection not in tabstate:
+ # tabstate.append(connection)
for tabname in tabstate:
try:
item = model.findItems(tabname)[0]

Modified: trunk/profit/workbench/widgets/ui_portfoliodisplay.ui
==============================================================================
--- trunk/profit/workbench/widgets/ui_portfoliodisplay.ui (original)
+++ trunk/profit/workbench/widgets/ui_portfoliodisplay.ui Sat Aug 2
15:20:12 2008
@@ -5,8 +5,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>461</width>
- <height>326</height>
+ <width>659</width>
+ <height>532</height>
</rect>
</property>
<property name="windowTitle" >
@@ -23,63 +23,7 @@
<widget class="FilterBar" native="1" name="filterBar" />
</item>
<item>
- <widget class="LocalTable" name="portfolioTable" >
- <property name="frameShape" >
- <enum>QFrame::NoFrame</enum>
- </property>
- <property name="frameShadow" >
- <enum>QFrame::Plain</enum>
- </property>
- <property name="selectionMode" >
- <enum>QAbstractItemView::SingleSelection</enum>
- </property>
- <property name="selectionBehavior" >
- <enum>QAbstractItemView::SelectRows</enum>
- </property>
- <property name="gridStyle" >
- <enum>Qt::DotLine</enum>
- </property>
- <column>
- <property name="text" >
- <string>Symbol</string>
- </property>
- </column>
- <column>
- <property name="text" >
- <string>Position</string>
- </property>
- </column>
- <column>
- <property name="text" >
- <string>Market Price</string>
- </property>
- </column>
- <column>
- <property name="text" >
- <string>Market Value</string>
- </property>
- </column>
- <column>
- <property name="text" >
- <string>Average Cost</string>
- </property>
- </column>
- <column>
- <property name="text" >
- <string>Unrealized Profit</string>
- </property>
- </column>
- <column>
- <property name="text" >
- <string>Realized Profit</string>
- </property>
- </column>
- <column>
- <property name="text" >
- <string>Account</string>
- </property>
- </column>
- </widget>
+ <widget class="QTreeView" name="portfolioView" />
</item>
</layout>
</widget>
@@ -88,11 +32,6 @@
<class>FilterBar</class>
<extends>QWidget</extends>
<header location="global" >profit.lib.widgets.filterbar.h</header>
- </customwidget>
- <customwidget>
- <class>LocalTable</class>
- <extends>QTableWidget</extends>
- <header location="global" >profit.lib.widgets.localtable.h</header>
</customwidget>
</customwidgets>
<resources/>

Reply all
Reply to author
Forward
0 new messages