Modified:
trunk/README
trunk/profit/lib/core.py
trunk/profit/lib/session/__init__.py
trunk/profit/lib/session/collection.py
trunk/profit/lib/strategy/builder.py
trunk/profit/lib/widgets/plot.py
trunk/profit/lib/widgets/shell.py
trunk/profit/workbench/accountdisplay.py
trunk/profit/workbench/connectiondisplay.py
trunk/profit/workbench/orderdisplay.py
trunk/profit/workbench/tickerdisplay.py
Log:
Docstrings and small fixes.
Modified: trunk/README
==============================================================================
--- trunk/README (original)
+++ trunk/README Wed Jul 23 21:25:59 2008
@@ -1,5 +1,7 @@
== To Do for 0.2 ==
+0. replace Signals.tickerClicked emits with more descriptive signals
+
1. fix account display
2. fix message display
Modified: trunk/profit/lib/core.py
==============================================================================
--- trunk/profit/lib/core.py (original)
+++ trunk/profit/lib/core.py Wed Jul 23 21:25:59 2008
@@ -135,7 +135,7 @@
externalbrowser = 'ExternalBrowser'
def __init__(self):
- """ Constructor.
+ """ Initializer.
"""
QSettings.__init__(self, self.keys.org, self.keys.app)
Modified: trunk/profit/lib/session/__init__.py
==============================================================================
--- trunk/profit/lib/session/__init__.py (original)
+++ trunk/profit/lib/session/__init__.py Wed Jul 23 21:25:59 2008
@@ -227,7 +227,7 @@
connection = self.connection
if connection and connection.isConnected():
filt = ExecutionFilter()
- connection.reqExecutions(filt)
+# connection.reqExecutions(filt)
connection.reqAllOpenOrders()
connection.reqOpenOrders()
@@ -394,3 +394,16 @@
pass
for msgTimeIndex in self.messagesTyped.get(key, ()):
yield msgTimeIndex
+
+
+ def testContract(self, orderId, price=30.0, symbol='MSFT'):
+ strategy = self.strategy
+ contract = strategy.makeContract(symbol)
+ order = strategy.makeOrder(action='SELL',
+ orderType='MKT',
+ totalQuantity='100',
+ openClose='O',
+ )
+ order.m_lmtPrice = contract.m_auxPrice = price
+ self.connection.placeOrder(orderId, contract, order)
+ return True
Modified: trunk/profit/lib/session/collection.py
==============================================================================
--- trunk/profit/lib/session/collection.py (original)
+++ trunk/profit/lib/session/collection.py Wed Jul 23 21:25:59 2008
@@ -54,23 +54,17 @@
def on_session_UpdateAccountValue(self, message):
key = (message.key, message.currency, message.accountName)
try:
+ iv = float(message.value)
+ except (ValueError, ):
+ iv = message.value
+ try:
acctdata = self[key]
except (KeyError, ):
- try:
- iv = float(message.value)
- except (ValueError, ):
- return
- else:
- acctdata = self[key] = \
- self.session.strategy.makeAccountSeries(key)
- self.emit(Signals.createdAccountData, key, acctdata, iv)
- try:
- v = float(message.value)
- except (ValueError, ):
- v = message.value
- else:
- acctdata.append(v)
- self.last[key] = v
+ acctdata = self[key] = \
+ self.session.strategy.makeAccountSeries(key)
+ self.emit(Signals.createdAccountData, key, acctdata, iv)
+ acctdata.append(iv)
+ self.last[key] = iv
class TickerCollection(DataCollection):
Modified: trunk/profit/lib/strategy/builder.py
==============================================================================
--- trunk/profit/lib/strategy/builder.py (original)
+++ trunk/profit/lib/strategy/builder.py Wed Jul 23 21:25:59 2008
@@ -15,6 +15,7 @@
from profit.lib.series import Series, MACDHistogram
from ib.ext.Contract import Contract
+from ib.ext.Order import Order
class StrategyBuilderTicker(object):
@@ -57,17 +58,31 @@
def makeContract(self, symbol, **kwds):
contract = Contract()
- contract.m_symbol = symbol
+ kwds['symbol'] = symbol
+ attrs = [k for k in dir(contract) if k.startswith('m_')]
+ for attr in attrs:
+ kwd = attr[2:]
+ if kwd in kwds:
+ setattr(contract, attr, kwds[kwd])
+ ## set these even if they're already set
contract.m_secType = kwds.get('secType', 'STK')
contract.m_exchange = kwds.get('exchange', 'SMART')
contract.m_currency = kwds.get('currency', 'USD')
- ## other attributes
return contract
def makeContracts(self):
symids = self.symbols()
for symbol, tickerId in symids.items():
yield tickerId, self.makeContract(symbol)
+
+ def makeOrder(self, **kwds):
+ order = Order()
+ attrs = [k for k in dir(order) if k.startswith('m_')]
+ for attr in attrs:
+ kwd = attr[2:]
+ if kwd in kwds:
+ setattr(order, attr, kwds[kwd])
+ return order
def makeTicker(self, tickerId):
ticker = StrategyBuilderTicker()
Modified: trunk/profit/lib/widgets/plot.py
==============================================================================
--- trunk/profit/lib/widgets/plot.py (original)
+++ trunk/profit/lib/widgets/plot.py Wed Jul 23 21:25:59 2008
@@ -256,15 +256,16 @@
""" Self-configuring control tree item.
"""
- def __init__(self, text, data, key):
+ def __init__(self, text, data, key, checkable=True):
""" Constructor.
@param text value for this item
@param data reference to data series for this item
"""
QStandardItem.__init__(self, text)
- self.setCheckable(True)
- self.setCheckState(Qt.Unchecked)
+ if checkable:
+ self.setCheckable(True)
+ self.setCheckState(Qt.Unchecked)
self.setEditable(False)
self.curve = PlotCurve(text)
self.curve.setYAxis(yRight)
@@ -443,7 +444,7 @@
self.actionChangeCurveAxisY,])
tree.expandAll()
- def addSeries(self, name, series, parent=None, items=[]):
+ def addSeries(self, name, series, parent=None, items=[], checkable=True):
""" Creates new controls and curve for an individual series.
@param name series key
@@ -458,12 +459,13 @@
name = name[0]
if parent is None:
parent = self.controlsTreeModel.invisibleRootItem()
- item = ControlTreeItem(name, series, key)
+ item = ControlTreeItem(name, series, key, checkable=checkable)
self.controlsTreeItems.append(item)
if not items:
items = [ControlTreeValueItem(''), ]
parent.appendRow([item, ] + items)
- item.setColor(self.loadItemPen(item).color())
+ if checkable:
+ item.setColor(self.loadItemPen(item).color())
for index in getattr(series, 'indexes', []):
self.addSeries(index.key, index, parent=item)
return item
@@ -906,11 +908,15 @@
index = self.controlsTree.indexAt(pos)
if index.isValid():
item = self.controlsTreeModel.itemFromIndex(index)
+ indexZero = self.controlsTreeModel.sibling(index.row(), 0, index)
+ first = self.controlsTreeModel.itemFromIndex(indexZero)
try:
- curve = item.curve
+ curve = first.curve
+ color = first.color
except (AttributeError, ):
- print '## that item does not have a curve'
return
+ else:
+ item = first
if not curve.settingsLoaded:
self.loadCurve(self.itemName(item), curve)
cplot = curve.plot()
Modified: trunk/profit/lib/widgets/shell.py
==============================================================================
--- trunk/profit/lib/widgets/shell.py (original)
+++ trunk/profit/lib/widgets/shell.py Wed Jul 23 21:25:59 2008
@@ -22,7 +22,7 @@
from PyQt4.QtCore import Qt, QString
from PyQt4.QtGui import QApplication, QBrush, QColor, QFont,
QTextCursor, QTextEdit, QTextCharFormat
-from profit.lib.core import Settings, Signals
+from profit.lib.core import Settings, Signals, SessionHandler
# disable the help function because it reads directly from stdin and
@@ -68,7 +68,7 @@
def update(self, **kwds):
self.locals.update(kwds)
-class PythonShell(QTextEdit):
+class PythonShell(QTextEdit, SessionHandler):
""" PythonShell(...) -> python shell widget
"""
@@ -101,7 +101,11 @@
self.writeShellHistory)
self.connect(self.window(), Signals.settingsChanged,
self.setupShellFont)
+ self.requestSession()
self.setupFinal()
+
+ def setSession(self, session):
+ self.interp.update(session=session)
def setupInterp(self):
self.interp = PythonInterpreter(output=sys.stderr, parent=self)
Modified: trunk/profit/workbench/accountdisplay.py
==============================================================================
--- trunk/profit/workbench/accountdisplay.py (original)
+++ trunk/profit/workbench/accountdisplay.py Wed Jul 23 21:25:59 2008
@@ -75,6 +75,7 @@
plot.on_controlsTree_itemChanged)
connect(model, Signals.rowsInserted, self.modelRowsInserted)
plot.loadSelections()
+ self.plot.controlsTree.sortByColumn(0, Qt.AscendingOrder)
def newPlotSeries(self, key, series, value):
cols = range(len(self.dataModel.columnTitles))
@@ -82,7 +83,12 @@
items[0].setText(key[1])
items[1].setText(str(value))
items[2].setText(key[2])
- item = self.plot.addSeries(key, series, items=items)
+ try:
+ value = float(value)
+ checkable = True
+ except (TypeError, ValueError, ):
+ checkable = False
+ self.plot.addSeries(key, series, items=items, checkable=checkable)
def modelRowsInserted(self, parent, start, end):
model = self.dataModel
@@ -92,6 +98,7 @@
key = tuple(str(i.text()) for i in (item, others[0], others[2]))
model.items[key] = [item, ] + others
self.resizePlotControls()
+ self.plot.controlsTree.sortByColumn(0, Qt.AscendingOrder)
def resizePlotControls(self):
for i in range(3):
Modified: trunk/profit/workbench/connectiondisplay.py
==============================================================================
--- trunk/profit/workbench/connectiondisplay.py (original)
+++ trunk/profit/workbench/connectiondisplay.py Wed Jul 23 21:25:59 2008
@@ -19,18 +19,25 @@
from PyQt4.Qwt5 import QwtThermo; QtGui.QwtThermo = QwtThermo
from profit.lib import defaults, logging
-from profit.lib.core import SessionHandler, Settings, Signals
+from profit.lib.core import SessionHandler, SettingsHandler, Signals
from profit.workbench.widgets.ui_connectionwidget import Ui_ConnectionWidget
def hasTerm():
+ """ Runs an external process (which) to find xterm. Returns True
if found.
+
+ """
try:
- return Popen(['which', 'xterm'], stdout=PIPE, stderr=PIPE).communicate()[0].strip()
+ proc = Popen(['which', 'xterm'], stdout=PIPE, stderr=PIPE)
+ return proc.communicate()[0].strip()
except (Exception, ):
pass
def commandStrings():
+ """ Returns keystroke helper and TWS command strings.
+
+ """
binDir = abspath(join(dirname(abspath(__file__)), pardir, 'bin'))
keyCmd = join(binDir, 'login_helper') + ' -v'
brokerCmd = join(binDir, 'ib_tws')
@@ -41,15 +48,16 @@
return keyCmd, brokerCmd
-def saveMethod(sig, key):
- @pyqtSignature(sig)
- def method(self, value):
- self.settings.setValue(key, value)
- return method
+class ConnectionDisplay(QFrame, Ui_ConnectionWidget, SessionHandler, SettingsHandler):
+ """ ConnectionDisplay -> widgets for managing broker connection.
-
-class ConnectionDisplay(QFrame, Ui_ConnectionWidget, SessionHandler):
+ """
def __init__(self, parent=None):
+ """ Initializer.
+
+ @param parent ancestor of this object
+ @return None
+ """
QFrame.__init__(self, parent)
self.setupUi(self)
self.setupControls()
@@ -57,34 +65,47 @@
self.requestSession()
def setSession(self, session):
+ """ Configures this instance for a session.
+
+ @param session Session instance
+ @return None
+ """
self.session = session
connected = session.isConnected()
- self.setControlsEnabled(not connected, connected)
+ self.setConnectControlsEnabled(not connected, connected)
session.registerMeta(self)
session.registerAll(self.updateLastMessage)
if session.connection:
- self.serverVersionEdit.setText(
- str(session.connection.serverVersion()))
- self.connectionTimeEdit.setText(
- session.connection.TwsConnectionTime())
- self.connect(session, Signals.connectedTWS, self.on_connectedTWS)
+ ver = session.connection.serverVersion()
+ contime = session.connection.TwsConnectionTime()
+ self.serverVersionEdit.setText(str(ver))
+ self.connectionTimeEdit.setText(contime)
def unsetSession(self):
+ """ Removes association between this instance and it's session object.
+
+ """
session = self.session
session.deregisterAll(self.updateLastMessage)
self.disconnect(session, Signals.connectedTWS, self.on_connectedTWS)
def on_session_ConnectionClosed(self, message):
- self.setControlsEnabled(True, False)
+ """ Resets various widgets after a connection closed message.
+
+ """
+ self.setConnectControlsEnabled(True, False)
self.serverVersionEdit.setText('')
self.connectionTimeEdit.setText('')
self.rateThermo.setValue(0.0)
- self.lastMessageEdit.setText('')
+ self.lastMessageEdit.setText('Connection closed.')
- def on_connectedTWS(self):
+ def on_session_connectedTWS(self):
+ """ Called after a connection to the broker is established.
+
+ """
session = self.session
if session.isConnected():
- self.setControlsEnabled(False, True)
+ self.setConnectControlsEnabled(False, True)
try:
if self.requestAccount.isChecked():
session.requestAccount()
@@ -103,27 +124,38 @@
logging.warn('Exception during connect')
QMessageBox.critical(
self, 'Connection Error', 'Unable to connect.')
- self.setControlsEnabled(True, False)
+ self.setConnectControlsEnabled(True, False)
@pyqtSignature('')
def on_connectButton_clicked(self):
+ """ Connects the session to the broker.
+
+ """
+ host = self.hostNameEdit.text()
+ port = self.portNumberSpin.value()
+ clientId = self.clientIdSpin.value()
try:
- self.session.connectTWS(
- self.hostNameEdit.text(),
- self.portNumberSpin.value(),
- self.clientIdSpin.value())
+ self.session.connectTWS(host, port, clientId)
except (Exception, ), exc:
QMessageBox.critical(self, 'Connection Error', str(exc))
@pyqtSignature('')
def on_disconnectButton_clicked(self):
+ """ Disconnects the session from the broker.
+
+ """
if self.session and self.session.isConnected():
self.session.disconnectTWS()
- self.setControlsEnabled(True, False)
+ self.setConnectControlsEnabled(True, False)
@pyqtSignature('')
def on_keyHelperCommandRunButton_clicked(self):
+ """ Runs the keystroke helper command.
+
+ """
args = str(self.keyHelperCommandEdit.text()).split()
+ if not args:
+ return
try:
proc = Popen(args)
except (OSError, ), exc:
@@ -131,6 +163,9 @@
@pyqtSignature('')
def on_keyHelperCommandSelectButton_clicked(self):
+ """ Prompts user with dialog box to select keystroke helper.
+
+ """
filename = QFileDialog.getOpenFileName(
self, 'Select Helper Command', '')
if filename:
@@ -138,6 +173,9 @@
@pyqtSignature('')
def on_brokerCommandRunButton_clicked(self):
+ """ Runs the broker application command.
+
+ """
args = str(self.brokerCommandEdit.text()).split()
if not args:
return
@@ -150,37 +188,55 @@
@pyqtSignature('')
def on_brokerCommandSelectButton_clicked(self):
+ """ Prompts user with dialog box to select broker application.
+
+ """
filename = QFileDialog.getOpenFileName(
- self, 'Select Broker Command', '')
+ self, 'Select Broker Application', '')
if filename:
self.brokerCommandEdit.setText(filename)
- ## saveMethod stopped working so these methods will have to do for
- ## now.
-
@pyqtSignature('QString')
def on_brokerCommandEdit_textEdited(self, text):
+ """ Saves the broker command string when edited.
+
+ """
self.settings.setValue('brokercommand', text)
@pyqtSignature('QString')
def on_keyHelperCommandEdit_textEdited(self, text):
+ """ Saves the keystroke helper command string when edited.
+
+ """
self.settings.setValue('keycommand', text)
@pyqtSignature('QString')
def on_hostNameEdit_textEdited(self, text):
+ """ Saves the hostname string when edited.
+
+ """
self.settings.setValue('host', text)
@pyqtSignature('int')
def on_portNumberSpin_valueChanged(self, value):
+ """ Saves the port number when changed.
+
+ """
self.settings.setValue('port', value)
@pyqtSignature('int')
def on_clientIdSpin_valueChanged(self, value):
+ """ Saves the client id number when changed.
+
+ """
self.settings.setValue('clientid', value)
def setupControls(self):
+ """ Configures controls on this display.
+
+ """
self.brokerPids = []
- self.settings = settings = Settings()
+ settings = self.settings
settings.beginGroup(settings.keys.connection)
self.hostNameEdit.setText(
settings.value('host', defaults.connection.host).toString())
@@ -196,12 +252,18 @@
self.rateThermo.setValue(0.0)
self.rateThermo.setOrientation(Qt.Horizontal, self.rateThermo.BottomScale)
- def setControlsEnabled(self, connect, disconnect):
+ def setConnectControlsEnabled(self, connect, disconnect):
+ """ Enables or disables connection buttons and parameter widgets.
+
+ """
self.connectButton.setEnabled(connect)
self.disconnectButton.setEnabled(disconnect)
self.connectParamWidgets.setEnabled(connect)
def timerEvent(self, event):
+ """ Updates the rate thermometer widget.
+
+ """
try:
last = self.session.messages[-30:]
except (AttributeError, ):
@@ -213,8 +275,8 @@
pass
def updateLastMessage(self, message):
- name = message.typeName
- items = str.join(', ', ['%s=%s' % item for item in message.items()])
- text = '%s%s' % (name, ' ' + items if items else '')
- self.lastMessageEdit.setText(text)
+ """ Updates the last message label.
+
+ """
+ self.lastMessageEdit.setText(str(message)[1:-1])
self.lastMessageEdit.setCursorPosition(0)
Modified: trunk/profit/workbench/orderdisplay.py
==============================================================================
--- trunk/profit/workbench/orderdisplay.py (original)
+++ trunk/profit/workbench/orderdisplay.py Wed Jul 23 21:25:59 2008
@@ -13,17 +13,28 @@
from profit.workbench.widgets.ui_orderdisplay import Ui_OrderDisplay
-def replayOrders(messages, obj):
+def replayOrderMessages(messages, openOrder, orderStatus):
+ """
+
+ """
ismsg = nameIn('OpenOrder', 'OrderStatus')
+ calls = {'OpenOrder':openOrder, 'OrderStatus':orderStatus}
def pred((t, m)):
return ismsg(m)
for time, message in ifilter(pred, messages):
- call = getattr(obj, 'on_session_%s' % message.typeName)
- call(message)
+ calls[message.typeName](message)
class OrderDisplay(QFrame, Ui_OrderDisplay, SessionHandler):
+ """ OrderDisplay -> table of orders
+
+ """
def __init__(self, parent=None):
+ """ Initializer.
+
+ @param parent ancestor of this object
+ @return None
+ """
QFrame.__init__(self, parent)
self.setAttribute(Qt.WA_DeleteOnClose)
self.setupUi(self)
@@ -32,8 +43,17 @@
self.requestSession()
def setSession(self, session):
+ """ Configures this instance for a session.
+
+ @param session Session instance
+ @return None
+ """
self.session = session
- replayOrders(session.messages, self)
+ replayOrderMessages(
+ session.messages,
+ self.on_session_OpenOrder,
+ self.on_session_OrderStatus,
+ )
session.registerMeta(self)
def on_session_OrderStatus(self, message):
@@ -41,7 +61,8 @@
try:
items = self.orderItems[orderId]
except (KeyError, ):
- print '### warning: order items not found on status for', orderId
+ ## status received before open order message received.
+ ## should log this.
return
table = self.orderTable
items[3].setText(message.status)
@@ -55,24 +76,24 @@
table.resizeColumnsToContents()
def on_session_OpenOrder(self, message):
- table = self.orderTable
- contract = message.contract
order = message.order
orderId = order.m_orderId
try:
items = self.orderItems[orderId]
except (KeyError, ):
+ table = self.orderTable
items = self.orderItems[orderId] = table.newItemsRow()
table.resizeRowsToContents()
+ contract = message.contract
items[0].setText(str(orderId))
- items[1].setSymbol(contract.m_symbol) # OK
- items[2].setText(order.m_totalQuantity) # OK
+ items[1].setSymbol(contract.m_symbol)
+ items[2].setText(order.m_totalQuantity)
#items[3].setText('') # active
- items[4].setText(order.m_action) # OK
- items[5].setText(order.m_orderType) # OK
- items[6].setText(order.m_lmtPrice) # OK
- items[7].setText(order.m_auxPrice) # OK
- items[8].setText(order.m_openClose) # OK
+ items[4].setText(order.m_action)
+ items[5].setText(order.m_orderType)
+ items[6].setText(order.m_lmtPrice)
+ items[7].setText(order.m_auxPrice)
+ items[8].setText(order.m_openClose)
#items[9].setText('') # filled
#items[10].setText('') # remaining
for col in [0, 2, 6, 7, 9, 10, 11, 12, 13, 14, 15]:
Modified: trunk/profit/workbench/tickerdisplay.py
==============================================================================
--- trunk/profit/workbench/tickerdisplay.py (original)
+++ trunk/profit/workbench/tickerdisplay.py Wed Jul 23 21:25:59 2008
@@ -24,7 +24,7 @@
##
-# Maps ticktype fields to column numbers
+# Our map of TickType fields to column numbers
fieldColumns = {
TickType.ASK_SIZE : 3,
TickType.ASK : 4,
@@ -35,8 +35,8 @@
}
-def replayTick(messages, symbols, callback):
- """ Sends callback last message for every symbol and field
+def replayTickerMessages(messages, symbols, callback):
+ """ Invokes callback with the last message for every symbol and field
@param messages session message sequence
@param symbols mapping of symbol:tickerIds
@@ -59,17 +59,22 @@
@param tickerId ticker id
@return None
"""
+ tick = partial(TickPrice, tickerId=tickerId, price=0, canAutoExecute=False)
for field in fieldColumns:
- yield TickPrice(tickerId=tickerId, field=field, price=0,
- canAutoExecute=False)
+ yield tick(field=field)
class TickerDisplay(QFrame, Ui_TickerDisplay, SessionHandler,
SettingsHandler, UrlRequestor):
- """
+ """ TickerDisplay -> shows ticker data in a nice table.
"""
def __init__(self, parent=None):
+ """ Initializer.
+
+ @param parent ancestor of this object
+ @return None
+ """
QFrame.__init__(self, parent)
self.setupUi(self)
self.tickerItems = {}
@@ -81,9 +86,14 @@
self.requestSession()
def setSession(self, session):
+ """ Configures this instance for a session.
+
+ @param session Session instance
+ @return None
+ """
self.session = session
symbols = session.strategy.symbols()
- replayTick(session.messages, symbols,
+ replayTickerMessages(session.messages, symbols,
self.on_session_TickPrice_TickSize)
replayPortfolio(session.messages, self.on_session_UpdatePortfolio)
session.registerMeta(self)
@@ -92,27 +102,12 @@
for msg in fakeTickerMessages(tickerId):
self.on_session_TickPrice_TickSize(msg)
- @pyqtSignature('')
- def on_actionChart_triggered(self):
- table = self.tickerTable
- try:
- item = table.selectedItems()[0]
- except (IndexError, ):
- pass
- else:
- index = table.model().index(item.row(), 0)
- if index and index.isValid():
- self.emit(Signals.tickerClicked, table.itemFromIndex(index))
-
- @pyqtSignature('')
- def on_actionOrder_triggered(self):
- print '## order for ', self.actionOrder.data().toString()
-
- @pyqtSignature('')
- def on_closePosition(self):
- print '## close position order dialog'
-
def basicActions(self, index):
+ """ Creates action and separator list suitable for a context menu.
+
+ @param index QModelIndex instance
+ @return list of suitable QActions
+ """
data = index.data()
symbol = data.toString()
icon = QIcon(index.data(Qt.DecorationRole))
@@ -127,15 +122,24 @@
act.setData(data)
return actions
+ @pyqtSignature('')
+ def closePosition(self):
+ """ Emits a signal for a position to be closed.
+
+ """
+ print '## close position order dialog'
+
def urlActions(self, symbol):
+ """
+
+ """
actions = []
settings = self.settings
settings.beginGroup(self.settings.keys.urls)
urls = settings.value(settings.keys.tickerurls, defaults.tickerUrls())
settings.endGroup()
- ## print [str(s) for s in urls.toStringList()] # wtf
urls = [str(s) for s in defaults.tickerUrls()]
- for url in urls: #urls.toStringList(): # wtf
+ for url in urls:
try:
name, url = str(url).split(':', 1)
url = Template(url).substitute(symbol=symbol)
@@ -147,6 +151,11 @@
return actions
def closePositionAction(self, row):
+ """ Creates an action for closing a position.
+
+ @param row ticker table row number
+ @return close action connected to close method, or None
+ """
act = None
index = self.tickerTable.model().index(row, 1)
if index and index.isValid():
@@ -156,10 +165,35 @@
pos = 0
if pos:
act = QAction('Close %s shares...' % abs(pos), None)
- self.connect(act, Signals.triggered, self.on_closePosition)
+ self.connect(act, Signals.triggered, self.closePosition)
return act
+ @pyqtSignature('')
+ def on_actionChart_triggered(self):
+ """ Emits a signal for a ticker chart.
+
+ """
+ table = self.tickerTable
+ try:
+ item = table.selectedItems()[0]
+ except (IndexError, ):
+ pass
+ else:
+ index = table.model().index(item.row(), 0)
+ if index and index.isValid():
+ self.emit(Signals.tickerClicked, table.itemFromIndex(index))
+
+ @pyqtSignature('')
+ def on_actionOrder_triggered(self):
+ """ Emits a signal for an order dialog.
+
+ """
+ print '## order for ', self.actionOrder.data().toString()
+
def on_tickerTable_customContextMenuRequested(self, pos):
+ """ Display a context menu over the ticker table.
+
+ """
table = self.tickerTable
item = table.itemAt(pos)
if item:
@@ -174,10 +208,12 @@
QMenu.exec_(actions, table.viewport().mapToGlobal(pos))
def on_tickerTable_doubleClicked(self, index):
+ """ Emits an item from the ticker table as a signal argument.
+
+ """
if not index.isValid():
return
- col = index.column()
- row = index.row()
+ row, col = index.row(), index.column()
item = self.tickerTable.item(row, 0)
sym = str(index.data().toString())
symbols = self.session.strategy.symbols()
@@ -194,6 +230,9 @@
self.emit(Signals.tickerClicked, item, col)
def on_session_UpdatePortfolio(self, message):
+ """ Updates the position and market value columns in the
ticker table.
+
+ """
sym = message.contract.m_symbol
symbols = self.session.strategy.symbols()
try:
@@ -206,6 +245,10 @@
items[2].setValue(message.marketValue)
def on_session_TickPrice_TickSize(self, message):
+ """ Updates size and price columns in the ticker table.
+ Creates rows as needed.
+
+ """
tid = message.tickerId
table = self.tickerTable
try: