/* ===========================================================
* TradeManager : a application to trade strategies for the Java(tm) platform
* ===========================================================
*
* (C) Copyright 2011-2011, by Simon Allen and Contributors.
*
* Project Info: org.trade
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library 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 Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
* [Java is a trademark or registered trademark of Oracle, Inc.
* in the United States and other countries.]
*
* (C) Copyright 2011-2011, by Simon Allen and Contributors.
*
* Original Author: Simon Allen;
* Contributor(s): -;
*
* Changes
* -------
*
*/
package org.trade.ui.contract;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.math.BigDecimal;
import java.text.NumberFormat;
import java.time.ZonedDateTime;
import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.JEditorPane;
import javax.swing.JFormattedTextField;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTabbedPane;
import javax.swing.JToolBar;
import javax.swing.ListSelectionModel;
import javax.swing.RowSorter;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.ToolTipManager;
import javax.swing.border.BevelBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreePath;
import org.trade.core.dao.Aspects;
import org.trade.core.properties.ConfigProperties;
import org.trade.core.util.CoreUtils;
import org.trade.core.util.TradingCalendar;
import org.trade.core.valuetype.Decode;
import org.trade.core.valuetype.Money;
import org.trade.dictionary.valuetype.BarSize;
import org.trade.dictionary.valuetype.DAOGroup;
import org.trade.dictionary.valuetype.DAOProfile;
import org.trade.dictionary.valuetype.AllocationMethod;
import org.trade.dictionary.valuetype.Side;
import org.trade.dictionary.valuetype.Tier;
import org.trade.dictionary.valuetype.TradestrategyStatus;
import org.trade.persistent.PersistentModel;
import org.trade.persistent.PersistentModelException;
import org.trade.persistent.dao.Candle;
import org.trade.persistent.dao.Contract;
import org.trade.persistent.dao.Portfolio;
import org.trade.persistent.dao.TradePosition;
import org.trade.persistent.dao.TradestrategyOrders;
import org.trade.persistent.dao.Strategy;
import org.trade.persistent.dao.TradeOrder;
import org.trade.persistent.dao.Tradestrategy;
import org.trade.persistent.dao.Tradingdays;
import org.trade.strategy.data.CandleDataset;
import org.trade.strategy.data.CandleSeries;
import org.trade.strategy.data.IndicatorSeries;
import org.trade.strategy.data.StrategyData;
import org.trade.ui.base.BaseButton;
import org.trade.ui.base.BasePanel;
import org.trade.ui.base.BaseUIPropertyCodes;
import org.trade.ui.base.TabbedAppPanel;
import org.trade.ui.base.TabbedCloseButton;
import org.trade.ui.base.Table;
import org.trade.ui.base.TextDialog;
import org.trade.ui.base.Tree;
import org.trade.ui.chart.CandlestickChart;
import org.trade.ui.models.TradeOrderTableModel;
import org.trade.ui.models.TradingdayTreeModel;
import org.trade.ui.tables.TradeOrderTable;
import org.trade.ui.tables.renderer.TradingdayTreeCellRenderer;
import org.trade.ui.widget.ButtonEditor;
import org.trade.ui.widget.ButtonRenderer;
import org.trade.ui.widget.DecodeComboBoxEditor;
import org.trade.ui.widget.DecodeComboBoxRenderer;
/**
*/
public class ContractPanel extends BasePanel implements TreeSelectionListener, ChangeListener, ItemListener {
/**
*
*/
private static final long serialVersionUID = 4026209743607182423L;
private Tradingdays m_tradingdays = null;
private PersistentModel m_tradePersistentModel = null;
private final JTabbedPane m_jTabbedPaneContract = new JTabbedPane();
private TradingdayTreeModel m_treeModel = null;
private Tree m_tree = null;
private Table m_tradeOrderTable = null;
private TradeOrderTableModel m_tradeOrderModel = null;
private JEditorPane m_tradeLabel = null;
private JEditorPane m_strategyLabel = null;
private BaseButton executeButton = null;
private BaseButton brokerDataButton = null;
private BaseButton cancelButton = null;
private BaseButton cancelStrategiesButton = null;
private BaseButton refreshButton = null;
private BaseButton closeAllButton = null;
private BaseButton closeAllPositionsButton = null;
private BaseButton propertiesButton = null;
private DecodeComboBoxEditor periodEditorComboBox = null;
private Integer backfillOffsetDays = 0;
private Boolean connected = new Boolean(false);
private static final NumberFormat currencyFormater = NumberFormat.getCurrencyInstance();
private static final SimpleAttributeSet bold = new SimpleAttributeSet();
private static final SimpleAttributeSet colorRedAttr = new SimpleAttributeSet();
private static final SimpleAttributeSet colorGreenAttr = new SimpleAttributeSet();
static {
StyleConstants.setBold(bold, true);
StyleConstants.setBackground(colorRedAttr, Color.RED);
StyleConstants.setBackground(colorGreenAttr, Color.GREEN);
}
/**
* Constructor for ContractPanel.
*
* @param tradingdays
* Tradingdays
* @param controller
* TabbedAppPanel
* @param tradePersistentModel
* PersistentModel
*/
public ContractPanel(Tradingdays tradingdays, TabbedAppPanel controller, PersistentModel tradePersistentModel) {
try {
if (null != getMenu())
getMenu().addMessageListener(this);
this.setLayout(new BorderLayout());
m_tradePersistentModel = tradePersistentModel;
m_tradingdays = tradingdays;
currencyFormater.setMinimumFractionDigits(2);
backfillOffsetDays = ConfigProperties.getPropAsInt("trade.backfill.offsetDays");
propertiesButton = new BaseButton(this, BaseUIPropertyCodes.PROPERTIES, 0);
propertiesButton.setEnabled(false);
executeButton = new BaseButton(controller, BaseUIPropertyCodes.EXECUTE);
executeButton.addMessageListener(this);
brokerDataButton = new BaseButton(controller, BaseUIPropertyCodes.DATA);
brokerDataButton.setToolTipText("Get Chart Data");
cancelButton = new BaseButton(controller, BaseUIPropertyCodes.CANCEL);
cancelButton.setToolTipText("Cancel Order");
cancelButton.setTransferObject(new Aspects());
cancelButton.addMessageListener(this);
cancelStrategiesButton = new BaseButton(controller, BaseUIPropertyCodes.CANCEL);
cancelStrategiesButton.setToolTipText("Cancel Strategy");
refreshButton = new BaseButton(this, BaseUIPropertyCodes.REFRESH);
closeAllButton = new BaseButton(this, BaseUIPropertyCodes.CLOSE_ALL);
closeAllPositionsButton = new BaseButton(controller, BaseUIPropertyCodes.CLOSE_ALL);
closeAllPositionsButton.setToolTipText("Cancel Orders & Close Position");
m_tradeOrderModel = new TradeOrderTableModel();
m_tradeOrderTable = new TradeOrderTable(m_tradeOrderModel);
m_tradeOrderTable.getSelectionModel().addListSelectionListener(new TradeOrderTableRowListener());
m_tradeOrderTable.setDefaultEditor(TradeOrder.class, new ButtonEditor(propertiesButton));
m_tradeOrderTable.setDefaultRenderer(TradeOrder.class, new ButtonRenderer(BaseUIPropertyCodes.PROPERTIES));
m_treeModel = new TradingdayTreeModel(m_tradingdays);
m_tree = new Tree(m_treeModel);
// Listen for when the selection changes.
m_tree.addTreeSelectionListener(this);
m_tree.setCellRenderer(new TradingdayTreeCellRenderer());
ToolTipManager.sharedInstance().registerComponent(m_tree);
JPanel jPanel1 = new JPanel(new BorderLayout());
JScrollPane jScrollPane1Tree = new JScrollPane();
jScrollPane1Tree.getViewport().add(m_tree, BorderLayout.CENTER);
JPanel jPanel2 = new JPanel(new BorderLayout());
jPanel2.add(jScrollPane1Tree, BorderLayout.CENTER);
jPanel2.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder("Tradingday"),
BorderFactory.createEmptyBorder(4, 4, 4, 4)));
jPanel1.setBorder(new BevelBorder(BevelBorder.LOWERED));
jPanel2.add(jPanel1, BorderLayout.NORTH);
// Chart Panel
JLabel jLabelPeriod = new JLabel("Period:");
periodEditorComboBox = new DecodeComboBoxEditor((new BarSize()).getCodesDecodes());
DecodeComboBoxRenderer periodRenderer = new DecodeComboBoxRenderer();
periodEditorComboBox.setRenderer(periodRenderer);
periodEditorComboBox.setItem(BarSize.newInstance(BarSize.FIVE_MIN));
periodEditorComboBox.setEnabled(false);
periodEditorComboBox.addItemListener(this);
JPanel jPanel6 = new JPanel(new FlowLayout(FlowLayout.LEFT));
jPanel6.setBorder(new BevelBorder(BevelBorder.RAISED));
jPanel6.add(closeAllButton, null);
jPanel6.add(brokerDataButton, null);
jPanel6.add(cancelStrategiesButton, null);
jPanel6.add(jLabelPeriod, null);
jPanel6.add(periodEditorComboBox, null);
JToolBar jToolBar = new JToolBar();
jToolBar.setLayout(new BorderLayout());
jToolBar.add(jPanel6);
m_strategyLabel = new JEditorPane("text/rtf", "");
m_strategyLabel.setAutoscrolls(false);
m_strategyLabel.setEditable(false);
m_tradeLabel = new JEditorPane("text/rtf", "");
m_tradeLabel.setAutoscrolls(false);
m_tradeLabel.setEditable(false);
JPanel jPanel12 = new JPanel(new BorderLayout());
jPanel12.add(m_strategyLabel, null);
JPanel jPanel18 = new JPanel(new BorderLayout());
jPanel18.add(jToolBar, BorderLayout.WEST);
JPanel jPanel11 = new JPanel(new BorderLayout());
jPanel11.add(jPanel18, BorderLayout.WEST);
jPanel11.add(jPanel12, BorderLayout.CENTER);
JPanel jPanel7 = new JPanel(new BorderLayout());
jPanel7.add(m_jTabbedPaneContract, BorderLayout.CENTER);
JScrollPane jScrollPane3 = new JScrollPane();
jScrollPane3.getViewport().add(jPanel7, BorderLayout.CENTER);
JPanel jPanel9 = new JPanel(new BorderLayout());
jPanel9.add(jScrollPane3, BorderLayout.CENTER);
jPanel9.add(jPanel11, BorderLayout.NORTH);
// Order Panel
m_tradeOrderTable.setFont(new Font("Monospaced", Font.PLAIN, 12));
JPanel jPanel5 = new JPanel(new FlowLayout(FlowLayout.LEFT));
jPanel5.add(executeButton, null);
jPanel5.add(cancelButton, null);
jPanel5.add(refreshButton, null);
jPanel5.add(closeAllPositionsButton, null);
jPanel5.setBorder(new BevelBorder(BevelBorder.RAISED));
JToolBar jToolBar1 = new JToolBar();
jToolBar1.setLayout(new BorderLayout());
jToolBar1.add(jPanel5);
JPanel jPanel19 = new JPanel(new BorderLayout());
jPanel19.add(jToolBar1, BorderLayout.WEST);
JScrollPane jScrollPane2 = new JScrollPane();
jScrollPane2.getViewport().add(m_tradeOrderTable, BorderLayout.CENTER);
jScrollPane2.setBorder(new BevelBorder(BevelBorder.LOWERED));
JPanel jPanel16 = new JPanel(new BorderLayout());
Dimension d = m_tradeOrderTable.getPreferredSize();
// Make changes to [i]d[/i] if you like...
m_tradeOrderTable.setPreferredScrollableViewportSize(d);
jScrollPane2.addMouseListener(m_tradeOrderTable);
JPanel jPanel17 = new JPanel(new BorderLayout());
jPanel17.add(jPanel19, BorderLayout.WEST);
jPanel17.add(m_tradeLabel, BorderLayout.CENTER);
jPanel16.add(jPanel17, BorderLayout.NORTH);
jPanel16.add(jScrollPane2, BorderLayout.CENTER);
// use the new JSplitPane to dynamically resize...
JSplitPane split = new JSplitPane(JSplitPane.VERTICAL_SPLIT, true, jPanel9, jPanel16);
split.setOneTouchExpandable(true);
split.setResizeWeight(0.8d);
JPanel jPanel15 = new JPanel(new BorderLayout());
jPanel15.add(split, BorderLayout.CENTER);
JSplitPane mainSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, jPanel2, jPanel15);
mainSplitPane.setOneTouchExpandable(true);
mainSplitPane.setResizeWeight(0.15d);
this.add(mainSplitPane, BorderLayout.CENTER);
m_jTabbedPaneContract.addChangeListener(this);
this.reFreshTab();
} catch (Exception ex) {
this.setErrorMessage("Error during initialization.", ex.getMessage(), ex);
}
}
public void doOpen() {
try {
m_treeModel.setData(m_tradingdays);
} catch (Exception ex) {
this.setErrorMessage("Error opening all tabs.", ex.getMessage(), ex);
}
}
/**
* Method doProperties.
*
* @param series
* IndicatorSeries
*/
public void doProperties(final TradeOrder instance) {
try {
if (null == instance.getTradestrategy().getPortfolio().getIndividualAccount()) {
AllocationMethodPanel allocationMethodPanel = new AllocationMethodPanel(instance);
if (null != allocationMethodPanel) {
TextDialog dialog = new TextDialog(this.getFrame(), "FA Account Properties", true,
allocationMethodPanel);
dialog.setLocationRelativeTo(this);
dialog.setVisible(true);
if (!dialog.getCancel()) {
if (null != instance.getFAProfile()) {
instance.setFAGroup(null);
instance.setFAMethod(null);
instance.setFAPercent(null);
instance.setAccountNumber(null);
} else {
if (null != instance.getFAGroup()) {
instance.setAccountNumber(null);
} else {
instance.setAccountNumber(instance.getTradestrategy().getPortfolio()
.getIndividualAccount().getAccountNumber());
}
}
}
}
} else {
this.setStatusBarMessage("No properties for Individual accounts ...\n", BasePanel.INFORMATION);
}
} catch (Exception ex) {
this.setErrorMessage("Error setting FA properties.", ex.getMessage(), ex);
}
}
public void doCancel(final Aspects aspects) {
this.setStatusBarMessage("Please select an order to cancel ...\n", BasePanel.INFORMATION);
}
public void doCloseAll() {
try {
int tabsCount = m_jTabbedPaneContract.getTabCount();
for (int index = 0; index < tabsCount; index++) {
doClose(new Integer(0));
}
m_tree.clearSelection();
} catch (Exception ex) {
this.setErrorMessage("Error removing all tabs.", ex.getMessage(), ex);
}
}
/**
* Method doClose.
*
* @param tradestrategy
* Tradestrategy
*/
public void doClose(final Tradestrategy tradestrategy) {
for (int index = 0; index < m_jTabbedPaneContract.getTabCount(); index++) {
ChartPanel chart = (ChartPanel) m_jTabbedPaneContract.getComponentAt(index);
if ((null != chart)
&& chart.getTradestrategy().getIdTradeStrategy().equals(tradestrategy.getIdTradeStrategy())) {
doClose(index);
break;
}
}
}
/**
* Method doClose.
*
* @param index
* Integer
*/
public void doClose(Integer index) {
ChartPanel chartPanel = (ChartPanel) m_jTabbedPaneContract.getComponentAt(index);
TabbedCloseButton tabbedCloseButton = (TabbedCloseButton) m_jTabbedPaneContract.getTabComponentAt(index);
tabbedCloseButton.removeMessageListener(this);
chartPanel.getCandlestickChart().removeChart();
chartPanel = null;
m_jTabbedPaneContract.remove(index);
m_tree.clearSelection();
}
public void doDelete() {
}
public void doExecute() {
this.setStatusBarMessage("Please select an order to execute ...\n", BasePanel.INFORMATION);
}
public void doWindowOpen() {
}
public void doWindowClose() {
}
public void doWindowActivated() {
try {
Object selectedObject = brokerDataButton.getTransferObject();
if (null == selectedObject) {
DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) m_tree.getLastSelectedPathComponent();
if (null != selectedNode)
selectedObject = selectedNode.getUserObject();
}
m_treeModel.setData(m_tradingdays);
// Expand the tree
for (int i = 0; i < m_tree.getRowCount(); i++) {
m_tree.expandRow(i);
}
TreePath path = m_tree.findTreePathByObject(selectedObject);
if (null != path) {
m_tree.setSelectionPath(path);
m_tree.scrollPathToVisible(path);
}
} catch (Exception ex) {
this.setErrorMessage("Error window activated.", ex.getMessage(), ex);
}
}
/**
* Method doWindowDeActivated.
*
* @return boolean
*/
public boolean doWindowDeActivated() {
return true;
}
public void doRefresh() {
ChartPanel currentTab = (ChartPanel) m_jTabbedPaneContract.getSelectedComponent();
if (null != currentTab)
doRefresh(currentTab.getTradestrategy());
}
/**
* Method doRefresh.
*
* @param tradestrategy
* Tradestrategy
*/
public void doRefresh(final Tradestrategy tradestrategy) {
try {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
getFrame().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
ChartPanel currentTab = (ChartPanel) m_jTabbedPaneContract.getSelectedComponent();
if (null != currentTab) {
if (currentTab.getTradestrategy().equals(tradestrategy)) {
reFreshTab();
}
}
} finally {
getFrame().setCursor(Cursor.getDefaultCursor());
}
}
});
} catch (Exception ex) {
setErrorMessage("Error refreshing Tradestrategy.", ex.getMessage(), ex);
}
}
/**
* Method valueChanged.
*
* @param e
* TreeSelectionEvent
* @see javax.swing.event.TreeSelectionListener#valueChanged(TreeSelectionEvent)
*/
public void valueChanged(TreeSelectionEvent evt) {
try {
/*
* Returns the last path element of the selection.This method is
* useful only when the selection model allows a single selection.
*/
TreePath path = evt.getNewLeadSelectionPath();
if (null == path) {
// Nothing is selected.
return;
}
Object nodeInfo = ((DefaultMutableTreeNode) path.getLastPathComponent()).getUserObject();
if (nodeInfo instanceof Tradestrategy) {
Tradestrategy tradestrategy = (Tradestrategy) nodeInfo;
periodEditorComboBox.setItem(BarSize.newInstance(tradestrategy.getBarSize()));
int currentTabIndex = -1;
for (int index = 0; index < m_jTabbedPaneContract.getTabCount(); index++) {
ChartPanel chartPanel = (ChartPanel) m_jTabbedPaneContract.getComponentAt(index);
if ((null != chartPanel) && chartPanel.getTradestrategy().getIdTradeStrategy()
.equals(tradestrategy.getIdTradeStrategy())) {
currentTabIndex = index;
break;
}
}
if (currentTabIndex == -1) {
ChartPanel chartPanel = createChartPanel(tradestrategy);
m_jTabbedPaneContract.add(chartPanel.getCandlestickChart().getName(), chartPanel);
currentTabIndex = m_jTabbedPaneContract.getTabCount() - 1;
m_jTabbedPaneContract.setTabComponentAt(currentTabIndex,
new TabbedCloseButton(m_jTabbedPaneContract, this));
}
m_jTabbedPaneContract.setSelectedIndex(currentTabIndex);
}
} catch (PersistentModelException ex) {
setErrorMessage("Error refreshing Tradestrategy.", ex.getMessage(), ex);
} catch (Exception ex) {
setErrorMessage("Error enabling chart.", ex.getMessage(), ex);
}
}
/**
* Method doTransfer. This method may be called from this panel or the
* Portfolio Tab or Trading Tab.
*
* @param tradestrategy
* Tradestrategy
*/
public void doTransfer(final Tradestrategy tradestrategy) {
brokerDataButton.setTransferObject(tradestrategy);
}
/**
* Method stateChanged. Different tab selected.
*
* @param evt
* ChangeEvent
* @see javax.swing.event.ChangeListener#stateChanged(ChangeEvent)
*/
public void stateChanged(ChangeEvent evt) {
// When a different tab is selected set the index
if (evt.getSource() instanceof JTabbedPane) {
JTabbedPane selectedTab = (JTabbedPane) evt.getSource();
if (selectedTab.isShowing()) {
this.reFreshTab();
}
}
}
/**
* Method setConnected.
*
* @param connected
* Boolean
*/
public void setConnected(Boolean connected) {
this.connected = connected;
this.reFreshTab();
}
/**
* Method itemStateChanged.
*
* @param e
* ItemEvent
* @see java.awt.event.ItemListener#itemStateChanged(ItemEvent)
*/
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
ChartPanel currentTab = (ChartPanel) m_jTabbedPaneContract.getSelectedComponent();
Integer newPeriod = new Integer(((BarSize) e.getItem()).getCode());
if (null != currentTab && !this.isConnected()) {
if (newPeriod.equals(BarSize.DAY)) {
newPeriod = currentTab.getTradestrategy().getBarSize();
}
if (!newPeriod.equals(
currentTab.getTradestrategy().getStrategyData().getCandleDataset().getSeries(0).getBarSize())) {
if (newPeriod.compareTo(currentTab.getTradestrategy().getBarSize()) > -1) {
currentTab.getTradestrategy().getStrategyData().changeCandleSeriesPeriod(newPeriod);
this.clearStatusBarMessage();
} else {
this.setStatusBarMessage("Time period not supported by candle series", BasePanel.WARNING);
}
}
}
}
}
/**
* Method isConnected.
*
* @return boolean
*/
private boolean isConnected() {
return this.connected;
}
/**
* Method createChartPanel.
*
* @param tradestrategy
* Tradestrategy
* @return ChartPanel
* @throws PersistentModelException
*/
private ChartPanel createChartPanel(Tradestrategy tradestrategy) throws PersistentModelException {
ZonedDateTime startDate = null;
ZonedDateTime endDate = null;
if (null == tradestrategy.getStrategyData()) {
tradestrategy.setStrategyData(StrategyData.create(tradestrategy));
}
if (tradestrategy.getStrategyData().getBaseCandleSeries().isEmpty()) {
endDate = TradingCalendar.getDateAtTime(
TradingCalendar.addTradingDays(tradestrategy.getTradingday().getClose(), backfillOffsetDays),
tradestrategy.getTradingday().getClose());
startDate = endDate.minusDays((tradestrategy.getChartDays() - 1));
startDate = TradingCalendar.getPrevTradingDay(startDate);
startDate = TradingCalendar.getDateAtTime(startDate, tradestrategy.getTradingday().getOpen());
List<Candle> candles = m_tradePersistentModel.findCandlesByContractDateRangeBarSize(
tradestrategy.getContract().getIdContract(), startDate, endDate, tradestrategy.getBarSize());
if (candles.isEmpty()) {
this.setStatusBarMessage("No chart data available for " + tradestrategy.getContract().getSymbol(),
BasePanel.INFORMATION);
} else {
// Populate the candle series.
CandleDataset.populateSeries(tradestrategy.getStrategyData(), candles);
candles.clear();
populateIndicatorCandleSeries(tradestrategy, startDate, endDate);
}
}
ChartPanel chartPanel = new ChartPanel(tradestrategy);
return chartPanel;
}
/**
* Method populateIndicatorCandleSeries. For any child indicators that are
* candle based create a Tradestrategy that will get the data. If this
* tradestrategy already exist share this with any other tradestrategy that
* requires this.
*
* @param tradestrategy
* Tradestrategy
* @param startDate
* Date
* @param endDate
* Date
* @throws PersistentModelException
*/
private void populateIndicatorCandleSeries(Tradestrategy tradestrategy, ZonedDateTime startDate,
ZonedDateTime endDate) throws PersistentModelException {
CandleDataset candleDataset = (CandleDataset) tradestrategy.getStrategyData()
.getIndicatorByType(IndicatorSeries.CandleSeries);
if (null != candleDataset) {
for (int seriesIndex = 0; seriesIndex < candleDataset.getSeriesCount(); seriesIndex++) {
CandleSeries series = candleDataset.getSeries(seriesIndex);
Contract contract = m_tradePersistentModel.findContractByUniqueKey(series.getSecType(),
series.getSymbol(), series.getExchange(), series.getCurrency(), null);
if (null != contract) {
Tradestrategy childTradestrategy = new Tradestrategy(contract, tradestrategy.getTradingday(),
new Strategy(), tradestrategy.getPortfolio(), new BigDecimal(0), null, null, false,
tradestrategy.getChartDays(), tradestrategy.getBarSize());
childTradestrategy.setDirty(false);
List<Candle> indicatorCandles = m_tradePersistentModel.findCandlesByContractDateRangeBarSize(
childTradestrategy.getContract().getIdContract(), startDate, endDate,
childTradestrategy.getBarSize());
if (indicatorCandles.isEmpty()) {
this.setStatusBarMessage(
"No chart data available for " + childTradestrategy.getContract().getSymbol(),
BasePanel.INFORMATION);
} else {
StrategyData strategyData = StrategyData.create(childTradestrategy);
CandleDataset.populateSeries(strategyData, indicatorCandles);
indicatorCandles.clear();
CandleSeries childSeries = strategyData.getBaseCandleSeries();
childSeries.setDisplaySeries(series.getDisplaySeries());
childSeries.setSeriesRGBColor(series.getSeriesRGBColor());
childSeries.setSubChart(series.getSubChart());
childSeries.setSymbol(series.getSymbol());
childSeries.setSecType(series.getSecType());
childSeries.setCurrency(series.getCurrency());
childSeries.setExchange(series.getExchange());
candleDataset.setSeries(seriesIndex, childSeries);
}
}
}
}
}
/**
*/
private class TradeOrderTableRowListener implements ListSelectionListener {
/**
* Method valueChanged.
*
* @param event
* ListSelectionEvent
* @see javax.swing.event.ListSelectionListener#valueChanged(ListSelectionEvent)
*/
public void valueChanged(ListSelectionEvent event) {
if (!event.getValueIsAdjusting()) {
ListSelectionModel model = (ListSelectionModel) event.getSource();
if (model.getLeadSelectionIndex() > -1) {
clearStatusBarMessage();
int row = m_tradeOrderTable.convertRowIndexToModel(model.getLeadSelectionIndex());
int i = 0;
for (TradeOrder tradeOrder : m_tradeOrderModel.getData().getTradeOrders()) {
if (i == row) {
cancelButton.setTransferObject(tradeOrder);
executeButton.setTransferObject(tradeOrder);
propertiesButton.setTransferObject(tradeOrder);
break;
}
i++;
}
} else {
cancelButton.setTransferObject(new Aspects());
executeButton.setTransferObject(null);
propertiesButton.setTransferObject(null);
}
}
}
}
/**
* Method setStrategyLabel.
*
* @param tradestrategy
* Tradestrategy
* @param candlestickChart
* CandlestickChart
* @throws BadLocationException
*/
private void setStrategyLabel(final Tradestrategy tradestrategy) {
try {
m_strategyLabel.setText(null);
String primaryExchange = "";
String industry = "";
String strategyDesc = "";
if (null != tradestrategy) {
primaryExchange = (tradestrategy.getContract().getPrimaryExchange() == null ? "No Data Available"
: tradestrategy.getContract().getPrimaryExchange());
industry = (tradestrategy.getContract().getIndustry() == null ? "No Data Available"
: tradestrategy.getContract().getIndustry());
strategyDesc = (tradestrategy.getStrategy().getDescription() == null ? "No Data Available"
: tradestrategy.getStrategy().getDescription());
}
CoreUtils.setDocumentText(m_strategyLabel.getDocument(), "Primary Exch: ", false, bold);
CoreUtils.setDocumentText(m_strategyLabel.getDocument(), CoreUtils.padRight(primaryExchange, 8), false,
null);
CoreUtils.setDocumentText(m_strategyLabel.getDocument(), " Industry:", false, bold);
CoreUtils.setDocumentText(m_strategyLabel.getDocument(), CoreUtils.padRight(industry, 30), false, null);
CoreUtils.setDocumentText(m_strategyLabel.getDocument(), "\n", false, null);
CoreUtils.setDocumentText(m_strategyLabel.getDocument(), "Strategy:", false, bold);
CoreUtils.setDocumentText(m_strategyLabel.getDocument(), CoreUtils.padRight(strategyDesc, 30), false, null);
} catch (Exception ex) {
this.setErrorMessage("Error setting Tradestrategy Label.", ex.getMessage(), ex);
}
}
/**
* Method reFreshTab.
*
* @throws BadLocationException
*/
private void reFreshTab() {
try {
this.clearStatusBarMessage();
Tradestrategy tradestrategy = null;
TradestrategyOrders tradestrategyOrders = null;
ChartPanel currentTab = (ChartPanel) m_jTabbedPaneContract.getSelectedComponent();
if (null == currentTab) {
m_tradeOrderModel.setData(new Tradestrategy());
closeAllPositionsButton.setTransferObject(new Tradestrategy());
} else {
/*
* Refresh the Tradestrategy this will get the latest orders.
*/
tradestrategy = m_tradePersistentModel.findTradestrategyById(currentTab.getTradestrategy());
tradestrategyOrders = m_tradePersistentModel
.findPositionOrdersByTradestrategyId(currentTab.getTradestrategy().getIdTradeStrategy());
currentTab.setTradestrategy(tradestrategy);
m_tradeOrderModel.setData(tradestrategy);
RowSorter<?> rsDetail = m_tradeOrderTable.getRowSorter();
rsDetail.setSortKeys(null);
periodEditorComboBox.setItem(BarSize.newInstance(tradestrategy.getBarSize()));
closeAllPositionsButton.setTransferObject(tradestrategy);
}
/*
* Refresh the header label above the chart and buttons.
*/
setStrategyLabel(tradestrategy);
enableChartButtons(tradestrategy);
double netValue = 0;
String openQuantity = "";
double commision = 0;
double unRealizedPL = 0;
double realizedPL = 0;
String symbol = "";
String side = "";
String tier = "";
String status = "";
String portfolio = "";
String risk = "";
if (null != tradestrategy) {
symbol = tradestrategy.getContract().getSymbol();
side = (tradestrategy.getSide() == null ? ""
: Side.newInstance(tradestrategy.getSide()).getDisplayName());
tier = (tradestrategy.getTier() == null ? ""
: Tier.newInstance(tradestrategy.getTier()).getDisplayName());
status = (tradestrategy.getStatus() == null ? ""
: TradestrategyStatus.newInstance(tradestrategy.getStatus()).getDisplayName());
portfolio = tradestrategy.getPortfolio().getName();
risk = currencyFormater.format(
(tradestrategy.getRiskAmount() == null ? 0 : tradestrategy.getRiskAmount().doubleValue()));
// Collections.sort(trade.getTradeOrders(), new
// TradeOrder());
/*
* Sum up orders that are filled and at the same time add the
* fill price. This happens when orders stop out as there are
* multiple stop orders for a position with multiple targets.
*/
TradeOrder prevTradeOrder = null;
Integer prevIdTradePosition = null;
for (TradeOrder order : tradestrategyOrders.getTradeOrders()) {
if (order.getIsFilled()) {
Integer quantity = order.getFilledQuantity();
if (null == prevIdTradePosition
|| prevIdTradePosition != order.getTradePosition().getIdTradePosition()) {
prevIdTradePosition = order.getTradePosition().getIdTradePosition();
}
if (null != prevTradeOrder) {
if (prevTradeOrder.getIsFilled()
&& prevTradeOrder.getFilledDate().equals(order.getFilledDate())
&& prevTradeOrder.getAverageFilledPrice().equals(order.getAverageFilledPrice())) {
quantity = quantity + prevTradeOrder.getFilledQuantity();
}
}
currentTab.getCandlestickChart().addBuySellTradeArrow(order.getAction(),
new Money(order.getAverageFilledPrice()), order.getFilledDate(), quantity);
}
prevTradeOrder = order;
}
if (null != prevIdTradePosition) {
TradePosition tradePosition = m_tradePersistentModel.findTradePositionById(prevIdTradePosition);
unRealizedPL = tradePosition
.getUnRealizedProfit(
tradestrategy.getStrategyData().getBaseCandleSeries().getContract().getLastPrice())
.doubleValue();
realizedPL = tradePosition.getRealizedProfit().doubleValue();
netValue = tradePosition.getTotalNetValue().doubleValue();
openQuantity = String.valueOf(Math.abs(tradePosition.getOpenQuantity()));
commision = tradePosition.getTotalCommission().doubleValue();
}
}
netValue = netValue - commision;
m_tradeLabel.setText(null);
CoreUtils.setDocumentText(m_tradeLabel.getDocument(), "Symbol:", false, bold);
CoreUtils.setDocumentText(m_tradeLabel.getDocument(), CoreUtils.padRight(symbol, 10), false, null);
CoreUtils.setDocumentText(m_tradeLabel.getDocument(), " Side:", false, bold);
CoreUtils.setDocumentText(m_tradeLabel.getDocument(), CoreUtils.padRight(side, 6), false, null);
CoreUtils.setDocumentText(m_tradeLabel.getDocument(), " Tier:", false, bold);
CoreUtils.setDocumentText(m_tradeLabel.getDocument(), CoreUtils.padRight(tier, 6), false, null);
CoreUtils.setDocumentText(m_tradeLabel.getDocument(), " Status:", false, bold);
CoreUtils.setDocumentText(m_tradeLabel.getDocument(), CoreUtils.padRight(status, 20), false, null);
CoreUtils.setDocumentText(m_tradeLabel.getDocument(), " Portfolio:", false, bold);
CoreUtils.setDocumentText(m_tradeLabel.getDocument(), CoreUtils.padRight(portfolio, 15), false, null);
CoreUtils.setDocumentText(m_tradeLabel.getDocument(), " Risk:", false, bold);
CoreUtils.setDocumentText(m_tradeLabel.getDocument(), CoreUtils.padLeft(risk, 10), false, null);
CoreUtils.setDocumentText(m_tradeLabel.getDocument(), "\n", false, null);
CoreUtils.setDocumentText(m_tradeLabel.getDocument(), "Net Total:", false, bold);
if (netValue < 0) {
CoreUtils.setDocumentText(m_tradeLabel.getDocument(),
CoreUtils.padLeft(currencyFormater.format(netValue), 10), false, colorRedAttr);
} else if (netValue > 0) {
CoreUtils.setDocumentText(m_tradeLabel.getDocument(),
CoreUtils.padLeft(currencyFormater.format(netValue), 10), false, colorGreenAttr);
} else {
CoreUtils.setDocumentText(m_tradeLabel.getDocument(),
CoreUtils.padLeft(currencyFormater.format(netValue), 10), false, null);
}
CoreUtils.setDocumentText(m_tradeLabel.getDocument(), " Realized P/L:", false, bold);
if (realizedPL < 0) {
CoreUtils.setDocumentText(m_tradeLabel.getDocument(),
CoreUtils.padLeft(currencyFormater.format(realizedPL), 10), false, colorRedAttr);
} else if (realizedPL > 0) {
CoreUtils.setDocumentText(m_tradeLabel.getDocument(),
CoreUtils.padLeft(currencyFormater.format(realizedPL), 10), false, colorGreenAttr);
} else {
CoreUtils.setDocumentText(m_tradeLabel.getDocument(),
CoreUtils.padLeft(currencyFormater.format(realizedPL), 10), false, null);
}
CoreUtils.setDocumentText(m_tradeLabel.getDocument(), " UnRealized P/L:", false, bold);
if (unRealizedPL < 0) {
CoreUtils.setDocumentText(m_tradeLabel.getDocument(),
CoreUtils.padLeft(currencyFormater.format(unRealizedPL), 10), false, colorRedAttr);
} else if (unRealizedPL > 0) {
CoreUtils.setDocumentText(m_tradeLabel.getDocument(),
CoreUtils.padLeft(currencyFormater.format(unRealizedPL), 10), false, colorGreenAttr);
} else {
CoreUtils.setDocumentText(m_tradeLabel.getDocument(),
CoreUtils.padLeft(currencyFormater.format(unRealizedPL), 10), false, null);
}
CoreUtils.setDocumentText(m_tradeLabel.getDocument(), " Open Qty:", false, bold);
CoreUtils.setDocumentText(m_tradeLabel.getDocument(), CoreUtils.padLeft(openQuantity, 10), false, null);
CoreUtils.setDocumentText(m_tradeLabel.getDocument(), " Comms:", false, bold);
CoreUtils.setDocumentText(m_tradeLabel.getDocument(),
CoreUtils.padLeft(currencyFormater.format(commision), 10), false, null);
} catch (Exception ex) {
this.setErrorMessage("Error refreshing Tab.", ex.getMessage(), ex);
}
}
/**
* Method enableChartButtons.
*
* @param tradestrategy
* Tradestrategy
* @throws Exception
*/
private void enableChartButtons(final Tradestrategy tradestrategy) throws Exception {
propertiesButton.setEnabled(false);
executeButton.setEnabled(false);
closeAllPositionsButton.setEnabled(false);
brokerDataButton.setEnabled(false);
cancelButton.setEnabled(false);
cancelStrategiesButton.setEnabled(false);
m_tradeOrderTable.enablePopupMenu(false);
periodEditorComboBox.setEnabled(false);
refreshButton.setEnabled(false);
brokerDataButton.setTransferObject(tradestrategy);
cancelStrategiesButton.setTransferObject(tradestrategy);
refreshButton.setTransferObject(tradestrategy);
if (null != tradestrategy) {
propertiesButton.setEnabled(true);
cancelStrategiesButton.setEnabled(true);
brokerDataButton.setEnabled(true);
if (this.isConnected()) {
executeButton.setEnabled(true);
refreshButton.setEnabled(true);
cancelButton.setEnabled(true);
closeAllPositionsButton.setEnabled(true);
m_tradeOrderTable.enablePopupMenu(true);
} else {
periodEditorComboBox.setEnabled(true);
}
}
}
/**
*/
class ChartPanel extends JPanel {
/**
*
*/
private static final long serialVersionUID = 6151552506157648783L;
private Tradestrategy tradestrategy = null;
private CandlestickChart candlestickChart = null;
/**
* Constructor for ChartPanel.
*
* @param tradestrategy
* Tradestrategy
*/
ChartPanel(Tradestrategy tradestrategy) {
this.tradestrategy = tradestrategy;
this.setLayout(new BorderLayout());
String ledgend = "(" + tradestrategy.getContract().getSymbol() + ") "
+ (tradestrategy.getContract().getLongName() == null ? "Contract details not available."
: tradestrategy.getContract().getLongName());
this.candlestickChart = new CandlestickChart(ledgend, tradestrategy.getStrategyData(),
tradestrategy.getTradingday());
this.candlestickChart.setName(tradestrategy.getContract().getSymbol());
this.add(this.candlestickChart);
}
/**
* Method getTradestrategy.
*
* @return Tradestrategy
*/
public Tradestrategy getTradestrategy() {
return this.tradestrategy;
}
/**
* Method setTradestrategy.
*
* @param tradestrategy
* Tradestrategy
*/
public void setTradestrategy(Tradestrategy tradestrategy) {
this.tradestrategy = tradestrategy;
}
/**
* Method getCandlestickChart.
*
* @return CandlestickChart
*/
public CandlestickChart getCandlestickChart() {
return this.candlestickChart;
}
}
/**
*/
class AllocationMethodPanel extends JPanel {
/**
*
*/
private static final long serialVersionUID = 5972331201407363985L;
/**
* Constructor for FAPropertiesPanel.
*
* @param tradeOrder
* TradeOrder
* @throws Exception
*/
public AllocationMethodPanel(final TradeOrder tradeOrder) throws Exception {
GridBagLayout gridBagLayout1 = new GridBagLayout();
JPanel jPanel1 = new JPanel(gridBagLayout1);
this.setLayout(new BorderLayout());
this.setBorder(
BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder("Select Profile or Group"),
BorderFactory.createEmptyBorder(4, 4, 4, 4)));
JLabel profileLabel = new JLabel("Profile: ");
profileLabel.setHorizontalTextPosition(SwingConstants.RIGHT);
profileLabel.setHorizontalAlignment(SwingConstants.RIGHT);
JLabel groupLabel = new JLabel("Group: ");
groupLabel.setHorizontalTextPosition(SwingConstants.RIGHT);
groupLabel.setHorizontalAlignment(SwingConstants.RIGHT);
JLabel mthodLabel = new JLabel("Method: ");
mthodLabel.setHorizontalTextPosition(SwingConstants.RIGHT);
mthodLabel.setHorizontalAlignment(SwingConstants.RIGHT);
JLabel percentLabel = new JLabel("Percent: ");
percentLabel.setHorizontalTextPosition(SwingConstants.RIGHT);
percentLabel.setHorizontalAlignment(SwingConstants.RIGHT);
DecodeComboBoxEditor profileEditorComboBox = new DecodeComboBoxEditor(
DAOProfile.newInstance().getCodesDecodes());
DecodeComboBoxRenderer profileTableRenderer = new DecodeComboBoxRenderer();
profileEditorComboBox.setRenderer(profileTableRenderer);
if (null != tradeOrder.getFAProfile())
profileEditorComboBox.setItem(DAOProfile.newInstance(tradeOrder.getFAProfile()));
profileEditorComboBox.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
if (!Decode.NONE.equals(((DAOProfile) e.getItem()).getDisplayName())) {
tradeOrder.setFAProfile(((Portfolio) ((DAOProfile) e.getItem()).getObject()).getName());
} else {
tradeOrder.setFAProfile(null);
}
}
}
});
DecodeComboBoxEditor groupEditorComboBox = new DecodeComboBoxEditor(
DAOGroup.newInstance().getCodesDecodes());
DecodeComboBoxRenderer groupTableRenderer = new DecodeComboBoxRenderer();
groupEditorComboBox.setRenderer(groupTableRenderer);
if (null != tradeOrder.getFAGroup())
groupEditorComboBox.setItem(DAOGroup.newInstance(tradeOrder.getFAGroup()));
groupEditorComboBox.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
if (!Decode.NONE.equals(((DAOGroup) e.getItem()).getDisplayName())) {
tradeOrder.setFAGroup(((Portfolio) ((DAOGroup) e.getItem()).getObject()).getName());
} else {
tradeOrder.setFAGroup(null);
}
}
}
});
DecodeComboBoxEditor methodEditorComboBox = new DecodeComboBoxEditor(
AllocationMethod.newInstance().getCodesDecodes());
DecodeComboBoxRenderer methodTableRenderer = new DecodeComboBoxRenderer();
methodEditorComboBox.setRenderer(methodTableRenderer);
if (null != tradeOrder.getFAMethod())
methodEditorComboBox.setItem(AllocationMethod.newInstance(tradeOrder.getFAMethod()));
methodEditorComboBox.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
if (!Decode.NONE.equals(((AllocationMethod) e.getItem()).getDisplayName())) {
tradeOrder.setFAMethod(((AllocationMethod) e.getItem()).getCode());
} else {
tradeOrder.setFAMethod(null);
}
}
}
});
NumberFormat percentFormat = NumberFormat.getNumberInstance();
percentFormat.setMinimumFractionDigits(2);
final JFormattedTextField percentTextField = new JFormattedTextField(percentFormat);
if (null != tradeOrder.getFAPercent())
percentTextField.setText(Integer.toString(new Integer(tradeOrder.getFAPercent().intValue())));
percentTextField.addPropertyChangeListener(new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent e) {
Object source = e.getSource();
if ("value".equals(e.getPropertyName())) {
if (source == percentTextField) {
if (percentTextField.isEditValid() && null != e.getNewValue()) {
Number rate = ((Number) percentTextField.getValue()).doubleValue();
tradeOrder.setFAPercent(new BigDecimal(rate.doubleValue()));
}
}
}
}
});
jPanel1.add(profileLabel, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.EAST,
GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 20, 5));
jPanel1.add(groupLabel, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.EAST,
GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 20, 5));
jPanel1.add(mthodLabel, new GridBagConstraints(0, 3, 1, 1, 0.0, 0.0, GridBagConstraints.EAST,
GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 20, 5));
jPanel1.add(percentLabel, new GridBagConstraints(0, 4, 1, 1, 0.0, 0.0, GridBagConstraints.EAST,
GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 20, 5));
jPanel1.add(profileEditorComboBox, new GridBagConstraints(1, 1, 1, 1, 0.0, 0.0, GridBagConstraints.WEST,
GridBagConstraints.HORIZONTAL, new Insets(2, 2, 2, 20), 20, 5));
jPanel1.add(groupEditorComboBox, new GridBagConstraints(1, 2, 1, 1, 0.0, 0.0, GridBagConstraints.WEST,
GridBagConstraints.HORIZONTAL, new Insets(2, 2, 2, 20), 20, 5));
jPanel1.add(methodEditorComboBox, new GridBagConstraints(1, 3, 1, 1, 0.0, 0.0, GridBagConstraints.WEST,
GridBagConstraints.HORIZONTAL, new Insets(2, 2, 2, 20), 20, 5));
jPanel1.add(percentTextField, new GridBagConstraints(1, 4, 1, 1, 0.0, 0.0, GridBagConstraints.WEST,
GridBagConstraints.HORIZONTAL, new Insets(2, 2, 2, 20), 20, 5));
this.add(jPanel1);
}
}
}