まめりうむ

WindowsからMacへ乗り換るためのネタをまとめたり好きなことをまとめたり。

*

JForexで約定履歴画面を自作する

      2017/06/12

スポンサーリンク

MT4もそうなんですけど、JForexも多くの国内業者に比べて約定履歴が見にくいです。

なので、簡易版ですが国内業者チックな見やすい約定履歴画面を自作したいと思います。

例によってGUIのパーツはEclipseとWindowBuilderでちゃちゃっと作ってます。

決済し終わったトレード

JForexでは未決済(保有中、待機中)のトレードと決済し終わったトレードは別々に管理されています。

未決済のトレードについてはIEngine.getOrders()メソッドなどで、決済し終わったトレードについてはIHistory.getHistory()メソッドで取得出来ます。

今回は取得期間を指定するようにして

private void fetchOrderHistory(Date startDt, Date stopDt) {
    orders.clear();

    IHistory history;
    Instrument instrument = (Instrument)cmbInstruments.getSelectedItem();
    try {
        history = context.getHistory();
        for (IOrder o: history.getOrdersHistory(instrument, startDt.getTime(), stopDt.getTime()))
            orders.add(o);
    } catch (JFException e) {
        e.printStackTrace();
    }
    //新規約定日時でソート
    class FillTimeComparator implements Comparator<IOrder> {
        @Override
        public int compare(IOrder o1, IOrder o2) {
            return o1.getFillTime() < o2.getFillTime() ? -1: 1;
        }
    }
    Collections.sort(orders, new FillTimeComparator());
}

こんな感じにしてます。

実際に取得してみると順序がバラバラなので一応ソートもしておきました。

全コード

package jforex;

import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.Vector;

import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableRowSorter;

import com.dukascopy.api.IAccount;
import com.dukascopy.api.IBar;
import com.dukascopy.api.IConsole;
import com.dukascopy.api.IContext;
import com.dukascopy.api.IHistory;
import com.dukascopy.api.IMessage;
import com.dukascopy.api.IOrder;
import com.dukascopy.api.IStrategy;
import com.dukascopy.api.ITick;
import com.dukascopy.api.Instrument;
import com.dukascopy.api.JFException;
import com.dukascopy.api.Period;

public class ClosedOrder01 extends JFrame implements IStrategy {
    private IContext context;
    private IConsole console;

    private ArrayList<IOrder> orders = new ArrayList<IOrder>();
    private JComboBox cmbInstruments;
    private JFormattedTextField txtStartDt;
    private JFormattedTextField txtStopDt;
    private JButton btnOpen;
    private JTable tblHistory;
    private DefaultTableModel tableModel;
    private JTextField txtAmountTotal;
    private JTextField txtTpTotal;
    private JTextField txtPipsTotal;

    public ClosedOrder01() {
        frameInitialize();
        addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosed(WindowEvent e) {
                try {
                    onStop();
                } catch (JFException e1) {
                    e1.printStackTrace();
                }
            }
        });
    }

    private void frameInitialize() {
        setTitle("約定履歴");
        setBounds(100, 100, 850, 510);
        GridBagLayout gridBagLayout = new GridBagLayout();
        gridBagLayout.columnWidths = new int[] {900};
        gridBagLayout.rowHeights = new int[] {30, 400, 30};
        gridBagLayout.columnWeights = new double[]{1.0};
        gridBagLayout.rowWeights = new double[]{0.0, 1.0, Double.MIN_VALUE};
        getContentPane().setLayout(gridBagLayout);

        JPanel pnlButton = new JPanel();
        GridBagConstraints gbc_pnlButton = new GridBagConstraints();
        gbc_pnlButton.fill = GridBagConstraints.BOTH;
        gbc_pnlButton.anchor = GridBagConstraints.NORTH;
        gbc_pnlButton.insets = new Insets(5, 0, 5, 0);
        gbc_pnlButton.gridx = 0;
        gbc_pnlButton.gridy = 0;
        getContentPane().add(pnlButton, gbc_pnlButton);
        GridBagLayout gbl_pnlButton = new GridBagLayout();
        gbl_pnlButton.columnWidths = new int[] {100, 50, 100, 50, 100, 100, 100};
        gbl_pnlButton.rowHeights = new int[] {30};
        pnlButton.setLayout(gbl_pnlButton);

        btnOpen = new JButton("表示");
        btnOpen.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");

                Date startDt = null;
                Date stopDt = null;
                try {
                    startDt = sdf.parse(txtStartDt.getText());
                    stopDt = sdf.parse(txtStopDt.getText());
                } catch (ParseException e1) {
                    e1.printStackTrace();
                }
                if (startDt != null && stopDt != null) {
                    fetchOrderHistory(startDt, stopDt);
                    setOrderHistory();
                }
            }
        });

		cmbInstruments = new JComboBox(getInstruments().toArray());
		GridBagConstraints gbc_cmbboxInstruments = new GridBagConstraints();
		gbc_cmbboxInstruments.fill = GridBagConstraints.BOTH;
		gbc_cmbboxInstruments.gridx = 0;
		gbc_cmbboxInstruments.gridy = 0;
		pnlButton.add(cmbInstruments, gbc_cmbboxInstruments);

		JLabel lblStartDt = new JLabel("開始:");
        lblStartDt.setHorizontalAlignment(SwingConstants.RIGHT);
        GridBagConstraints gbc_lblStartDt = new GridBagConstraints();
        gbc_lblStartDt.fill = GridBagConstraints.BOTH;
        gbc_lblStartDt.gridx = 1;
        gbc_lblStartDt.gridy = 0;
        pnlButton.add(lblStartDt, gbc_lblStartDt);

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
        Calendar calendar = Calendar.getInstance();

        calendar.add(Calendar.DAY_OF_MONTH, 0);

        txtStartDt = new JFormattedTextField(sdf);
        txtStartDt.setHorizontalAlignment(SwingConstants.CENTER);
        txtStartDt.setText(sdf.format(calendar.getTime()));
        GridBagConstraints gbc_txtStartDt = new GridBagConstraints();
        gbc_txtStartDt.fill = GridBagConstraints.BOTH;
        gbc_txtStartDt.gridx = 2;
        gbc_txtStartDt.gridy = 0;
        pnlButton.add(txtStartDt, gbc_txtStartDt);

        JLabel lblStopDt = new JLabel("終了:");
        lblStopDt.setHorizontalAlignment(SwingConstants.RIGHT);
        GridBagConstraints gbc_lblStopDt = new GridBagConstraints();
        gbc_lblStopDt.fill = GridBagConstraints.BOTH;
        gbc_lblStopDt.gridx = 3;
        gbc_lblStopDt.gridy = 0;
        pnlButton.add(lblStopDt, gbc_lblStopDt);

        calendar.add(Calendar.DAY_OF_MONTH, 1);

        txtStopDt = new JFormattedTextField(sdf);
        txtStopDt.setHorizontalAlignment(SwingConstants.CENTER);
        txtStopDt.setText(sdf.format(calendar.getTime()));
        GridBagConstraints gbc_txtStopDt = new GridBagConstraints();
        gbc_txtStopDt.fill = GridBagConstraints.BOTH;
        gbc_txtStopDt.gridx = 4;
        gbc_txtStopDt.gridy = 0;
        pnlButton.add(txtStopDt, gbc_txtStopDt);
        GridBagConstraints gbc_btnOpen = new GridBagConstraints();
        gbc_btnOpen.insets = new Insets(0, 5, 0, 5);
        gbc_btnOpen.fill = GridBagConstraints.BOTH;
        gbc_btnOpen.gridx = 5;
        gbc_btnOpen.gridy = 0;
        pnlButton.add(btnOpen, gbc_btnOpen);

        JScrollPane scrollPane = new JScrollPane();
        GridBagConstraints gbc_scrollPane = new GridBagConstraints();
        gbc_scrollPane.weighty = 1.0;
        gbc_scrollPane.weightx = 1.0;
        gbc_scrollPane.fill = GridBagConstraints.BOTH;
        gbc_scrollPane.gridx = 0;
        gbc_scrollPane.gridy = 1;
        getContentPane().add(scrollPane, gbc_scrollPane);


        Object[] colName = {"新規約定日時","決済約定日時","通貨ペア","新規売買","Lot数","新規約定値","決済約定値","損益pips","損益","ID"};
        tableModel = new DefaultTableModel(colName, 0);

        tblHistory = new JTable(tableModel);
        tblHistory.setRowSorter(new TableRowSorter(tableModel));
        tblHistory.setEnabled(false);
        tblHistory.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
        scrollPane.setViewportView(tblHistory);

        JPanel pnlSummary = new JPanel();
        GridBagConstraints gbc_pnlSummary = new GridBagConstraints();
        gbc_pnlSummary.insets = new Insets(5, 0, 5, 0);
        gbc_pnlSummary.anchor = GridBagConstraints.SOUTH;
        gbc_pnlSummary.gridx = 0;
        gbc_pnlSummary.gridy = 2;
        getContentPane().add(pnlSummary, gbc_pnlSummary);
        GridBagLayout gbl_pnlSummary = new GridBagLayout();
        gbl_pnlSummary.columnWidths = new int[] {100, 100, 100, 100, 100, 100};
        gbl_pnlSummary.rowHeights = new int[] {30};
        pnlSummary.setLayout(gbl_pnlSummary);

        JLabel lblAmountTotal = new JLabel("Lot数合計:");
        lblAmountTotal.setHorizontalAlignment(SwingConstants.RIGHT);
        GridBagConstraints gbc_lblAmountTotal = new GridBagConstraints();
        gbc_lblAmountTotal.fill = GridBagConstraints.BOTH;
        gbc_lblAmountTotal.gridx = 0;
        gbc_lblAmountTotal.gridy = 0;
        pnlSummary.add(lblAmountTotal, gbc_lblAmountTotal);

        txtAmountTotal = new JTextField();
        txtAmountTotal.setHorizontalAlignment(SwingConstants.CENTER);
        GridBagConstraints gbc_txtAmountTotal = new GridBagConstraints();
        gbc_txtAmountTotal.fill = GridBagConstraints.BOTH;
        gbc_txtAmountTotal.gridx = 1;
        gbc_txtAmountTotal.gridy = 0;
        pnlSummary.add(txtAmountTotal, gbc_txtAmountTotal);
        txtAmountTotal.setColumns(10);

        JLabel lblTpTotal = new JLabel("損益合計:");
        lblTpTotal.setHorizontalAlignment(SwingConstants.RIGHT);
        GridBagConstraints gbc_lblTpTotal = new GridBagConstraints();
        gbc_lblTpTotal.fill = GridBagConstraints.BOTH;
        gbc_lblTpTotal.gridx = 2;
        gbc_lblTpTotal.gridy = 0;
        pnlSummary.add(lblTpTotal, gbc_lblTpTotal);

        txtTpTotal = new JTextField();
        txtTpTotal.setHorizontalAlignment(SwingConstants.CENTER);
        txtTpTotal.setColumns(10);
        GridBagConstraints gbc_txtTpTotal = new GridBagConstraints();
        gbc_txtTpTotal.fill = GridBagConstraints.BOTH;
        gbc_txtTpTotal.gridx = 3;
        gbc_txtTpTotal.gridy = 0;
        pnlSummary.add(txtTpTotal, gbc_txtTpTotal);

        JLabel lblPipsTotal = new JLabel("pips合計:");
        lblPipsTotal.setHorizontalAlignment(SwingConstants.RIGHT);
        GridBagConstraints gbc_lblPipsTotal = new GridBagConstraints();
        gbc_lblPipsTotal.fill = GridBagConstraints.BOTH;
        gbc_lblPipsTotal.gridx = 4;
        gbc_lblPipsTotal.gridy = 0;
        pnlSummary.add(lblPipsTotal, gbc_lblPipsTotal);

        txtPipsTotal = new JTextField();
        txtPipsTotal.setHorizontalAlignment(SwingConstants.CENTER);
        txtPipsTotal.setColumns(10);
        GridBagConstraints gbc_txtPipsTotal = new GridBagConstraints();
        gbc_txtPipsTotal.fill = GridBagConstraints.BOTH;
        gbc_txtPipsTotal.gridx = 5;
        gbc_txtPipsTotal.gridy = 0;
        pnlSummary.add(txtPipsTotal, gbc_txtPipsTotal);
}

    private void fetchOrderHistory(Date startDt, Date stopDt) {
        orders.clear();

        IHistory history;
        Instrument instrument = (Instrument)cmbInstruments.getSelectedItem();
        try {
            history = context.getHistory();
            for (IOrder o: history.getOrdersHistory(instrument, startDt.getTime(), stopDt.getTime()))
                orders.add(o);
        } catch (JFException e) {
            e.printStackTrace();
        }
        //新規約定日時でソート
        class FillTimeComparator implements Comparator<IOrder> {
            @Override
            public int compare(IOrder o1, IOrder o2) {
                return o1.getFillTime() < o2.getFillTime() ? -1: 1;
            }
        }
        Collections.sort(orders, new FillTimeComparator());
    }

    private void setOrderHistory() {

        DefaultTableModel model = (DefaultTableModel)tblHistory.getModel();
        model.setRowCount(0);

        double amountTotal = 0.0D;
        double tpTotal = 0.0D;
        double pipsTotal = 0.0D;

        for (IOrder o: orders) {

            SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
            long fillTime = o.getFillTime();
            long closeTime = o.getCloseTime();
            Instrument instrument = o.getInstrument();
            String scaleFormat ="%." + String.valueOf(instrument.getPipScale() + 1) + "f";
            String entryOrderSide;
            entryOrderSide = o.isLong() ? "買" : "売";
            double amount = o.getAmount() * 100.0D;
            double openPrice = o.getOpenPrice();
            double closePrice = o.getClosePrice();
            double profitPips = o.getProfitLossInPips();
            double profitAmount = o.getProfitLossInAccountCurrency();


            tableModel.addRow(new Object[] {
                    sdf.format(fillTime),
                    sdf.format(closeTime),
                    instrument.toString(),
                    entryOrderSide,
                    String.format("%,.0f", amount),
                    String.format(scaleFormat, openPrice),
                    String.format(scaleFormat, closePrice),
                    String.format("%,.1f", profitPips),
                    String.format("%,.0f", profitAmount),
                    o.getId()});

            amountTotal += o.getAmount();
            tpTotal += o.getProfitLossInAccountCurrency();
            pipsTotal += o.getProfitLossInPips();
        }
        txtAmountTotal.setText(String.format("%,.2f", amountTotal));
        txtTpTotal.setText(String.format("%,.0f", tpTotal));
        txtPipsTotal.setText(String.format("%,.1f", pipsTotal));
    }

    @Override
    public void onStart(IContext context) throws JFException {
        this.context = context;
        console = context.getConsole();

        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
        console.getOut().println("Strategy Started.");
    }

    @Override
    public void onTick(Instrument instrument, ITick tick) throws JFException {
    }
    @Override
    public void onBar(Instrument instrument, Period period, IBar askBar, IBar bidBar) throws JFException {
    }
    @Override
    public void onMessage(IMessage message) throws JFException {
    }
    @Override
    public void onAccount(IAccount account) throws JFException {
    }
    @Override
    public void onStop() throws JFException {
        console.getOut().println("Strategy Stopped.");
    }
    //通貨ペア
    private final Vector<Instrument> getInstruments() {
        Vector<Instrument> instruments = new Vector<Instrument>();
        instruments.add(Instrument.USDJPY);
        instruments.add(Instrument.EURUSD);
        instruments.add(Instrument.EURJPY);
        instruments.add(Instrument.GBPUSD);
        instruments.add(Instrument.GBPJPY);
        instruments.add(Instrument.AUDUSD);
        instruments.add(Instrument.AUDJPY);

        return instruments;
    }
}

今までの注文画面と違いコールバック関数もほとんど使ってないので内容的には大したことないですねw

もっと綺麗なコーディングをしたいんですがスキルないのが悲しいです(;_;

 - FX, プログラミング

スポンサーリンク

Message

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)

  関連記事

Pythonでニコ生アラートを作る(放送通知サーバをクラス化する)

前回までのスクリプトでニコ生の放送通知を受け取ることが出来たので、今回はもう少し …

JForexでスタンドアローンアプリを自作する

前回まではJForexs採用業者で提供されているチャートツールへの追加機能として …

JForexで注文画面を自作する(新規注文に有効期限を設定)

前回作成した指値・逆指値注文画面のときにまとめて作ってしまえば良かったんですが忘 …

[Python]try~finally文中でreturn文を使ったときの動作

Pythonドキュメントの日本語訳を読んでて気付いたんですが return によ …

Pythonチュートリアルを読みました

Pythonを勉強するにあたって、最初にPythonスタートブックという本を読み …

JForexで注文画面を自作する(指値・逆指値注文)

前回までで一応成行注文に最低限欲しい機能は付けられましたので、今回は指値・逆指値 …

リーダブルコードを読みました

ひょんなことからクオカード1,000円分が手に入ったので、前から読んでみたかった …

JForexで注文画面を自作する(スプレッド表示と新規注文時のオプション)

前回までで成行注文と全決済が出来るようになったので、今回はもう少し使い勝手を良く …

Pythonスタートブックを読みました

Sublime Text3きっかけで、前からちょっと触ってみたいなと思ってたスク …

Pythonのlxmlモジュールをインストールする

Pythonの勉強のためにYahoo!の検索結果からタイトルとリンクを抽出するP …