net.tradelib.misc.StrategyText.java Source code

Java tutorial

Introduction

Here is the source code for net.tradelib.misc.StrategyText.java

Source

// Copyright 2015 Ivan Popivanov
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package net.tradelib.misc;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Timestamp;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVPrinter;

import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;

public class StrategyText {

    public static String build(String dbUrl, String strategy, LocalDate date, String sep) throws Exception {
        return build(dbUrl, strategy, date, sep, null, ',');
    }

    public static String build(String dbUrl, String strategy, LocalDate date, String sep, String csvPath,
            char csvSep) throws Exception {
        String text = "";

        Connection connection = DriverManager.getConnection(dbUrl);

        List<InstrumentText> lit = StrategyText.buildList(connection, strategy, date, csvPath, csvSep);
        for (InstrumentText it : lit) {
            if (!it.isSection()) {
                text += String.format("\n%20s" + sep + "%4s" + sep + "%10s" + sep + "%s", it.getName(),
                        it.getSymbol(), it.getExpiration(), it.getStatus());
            }
        }

        connection.close();

        return text;
    }

    private static final String STRATEGY_QUERY = " select c.id as cid, c.name as cname, i.comment as name, coalesce(ivar.symbol, spos.symbol) as symbol, "
            + "     spos.position as position, date(spos.ts/1000.0, 'unixepoch') as date, spos.last_close as close, "
            + "     spos.last_ts as close_date, "
            + "     spos.details AS details, strftime('%m''%Y',i.current_contract/1000.0,'unixepoch') as current_contract, "
            + "     strftime('%m''%Y',i.next_contract/1000.0,'unixepoch') as next_contract, i.trading_days as days, "
            + "     strftime('%m''%Y',i.current_contract2/1000.0,'unixepoch') as current_contract2, i.roll_today as roll_today "
            + " from strategy_positions spos " + " inner join strategies s on s.id = spos.strategy_id "
            + " inner join instrument i on i.symbol = spos.symbol and i.provider = 'csi' "
            + " left join instrument_variation ivar on spos.symbol = ivar.original_symbol and ivar.original_provider = 'csi' "
            + " left join instrument_visiable iv on iv.instrument_id = i.id "
            + " left join categories c on iv.categories_id = c.id "
            + " WHERE s.name = ? AND strftime('%Y-%m-%d', spos.last_ts/1000.0, 'unixepoch') = strftime('%Y-%m-%d', ?/1000.0, 'unixepoch') "
            + " ORDER BY cid, iv.ord";

    private static final String STRATEGY_QUERY_MYSQL = " select c.id as cid, c.name as cname, i.comment as name, coalesce(ivar.symbol, spos.symbol) as symbol, "
            + "     spos.position as position, date_format(spos.ts, '%Y-%m-%d') as date, spos.last_close as close, "
            + "     spos.last_ts as close_date, "
            + "     spos.details AS details, date_format(i.current_contract,'%b\\'%y') as current_contract, "
            + "     date_format(i.next_contract,'%b\\'%y') as next_contract, i.trading_days as days, "
            + "     date_format(i.current_contract2,'%b\\'%y') as current_contract2, i.roll_today as roll_today "
            + " from strategy_positions spos " + " inner join strategies s on s.id = spos.strategy_id "
            + " inner join instrument i on i.symbol = spos.symbol and i.provider = 'csi' "
            + " left join instrument_variation ivar on spos.symbol = ivar.original_symbol and ivar.original_provider = 'csi' "
            + " left join instrument_visiable iv on iv.instrument_id = i.id "
            + " left join categories c on iv.categories_id = c.id "
            + " WHERE s.name = ? AND DATE(spos.last_ts) = DATE(?) " + " ORDER BY cid, iv.ord";

    public static List<InstrumentText> buildList(Connection con, String strategy, LocalDate date, String csvPath,
            char csvSep) throws Exception {
        // public static List<InstrumentText> buildList(Connection con, String strategy, LocalDate date) throws Exception {
        ArrayList<InstrumentText> result = new ArrayList<InstrumentText>();

        CSVPrinter printer = null;
        if (csvPath != null) {
            // Add withHeader for headers
            printer = CSVFormat.DEFAULT.withDelimiter(csvSep).print(new BufferedWriter(new FileWriter(csvPath)));
        }

        int numCsvColumns = 12;

        int rollMethod = 2;

        DatabaseMetaData dmd = con.getMetaData();
        String driverName = dmd.getDriverName();
        String query = "";
        if (driverName.startsWith("MySQL")) {
            query = STRATEGY_QUERY_MYSQL;
        } else {
            query = STRATEGY_QUERY;
        }

        String prevCategory = "";
        PreparedStatement pstmt = con.prepareStatement(query);
        pstmt.setString(1, strategy);
        pstmt.setTimestamp(2, Timestamp.valueOf(date.atStartOfDay()));
        ResultSet rs = pstmt.executeQuery();
        while (rs.next()) {
            String category = rs.getString(2);
            if (!category.equals(prevCategory)) {
                result.add(InstrumentText.makeSection(category));
                prevCategory = category;

                if (printer != null) {
                    printer.print(category);
                    for (int ii = 1; ii < numCsvColumns; ++ii) {
                        printer.print("");
                    }
                    printer.println();
                }
            }
            String name = rs.getString(3);
            String symbol = rs.getString(4);
            String contract = "";
            if (rollMethod == 1) {
                // Uses current_contract and trading_days
                int ndays = rs.getInt(12);
                if (ndays > 1) {
                    contract = rs.getString(10);
                } else {
                    contract = "Roll to " + rs.getString(11);
                }
            } else if (rollMethod == 2) {
                // Uses current_contract2 and roll_today
                int rollToday = rs.getInt(14);
                if (rollToday == 0) {
                    contract = rs.getString(13);
                } else {
                    contract = "Roll to " + rs.getString(13);
                }
            }

            if (printer != null) {
                printer.print(name);
                printer.print(symbol);
                printer.print(contract);
            }

            String signal;
            long position = (long) rs.getDouble(5);
            JsonObject jo = new Gson().fromJson(rs.getString(9), JsonObject.class);
            if (position > 0.0) {
                BigDecimal entryPrice;
                double pnl;
                try {
                    entryPrice = jo.get("entry_price").getAsBigDecimal();
                    pnl = jo.get("pnl").getAsDouble();
                } catch (Exception e) {
                    entryPrice = BigDecimal.valueOf(Double.MIN_VALUE);
                    pnl = Double.MIN_VALUE;
                }
                signal = String.format("Long [%d] since %s [at %s].", position, rs.getString(6),
                        formatBigDecimal(entryPrice));
                if (printer != null)
                    printer.print(signal);
                String openProfit = String.format("Open equity profit %,d.", (int) Math.floor(pnl));
                signal += " " + openProfit;
                if (printer != null)
                    printer.print(openProfit);
            } else if (position < 0.0) {
                BigDecimal entryPrice;
                double pnl;
                try {
                    entryPrice = jo.get("entry_price").getAsBigDecimal();
                    pnl = jo.get("pnl").getAsDouble();
                } catch (Exception e) {
                    entryPrice = BigDecimal.valueOf(-1);
                    pnl = -1;
                }
                signal = String.format("Short [%d] since %s [at %s].", Math.abs(position), rs.getString(6),
                        formatBigDecimal(entryPrice));
                if (printer != null)
                    printer.print(signal);
                String openProfit = String.format("Open equity profit %,d.", (int) Math.floor(pnl));
                signal += " " + openProfit;
                if (printer != null)
                    printer.print(openProfit);
            } else {
                signal = "Out.";
                if (printer != null) {
                    printer.print(signal);
                    // An empty column follows the status if there is no position - there is no profit.
                    printer.print("");
                }
            }

            boolean hasOrder = false;
            JsonArray ja = jo.get("orders").getAsJsonArray();
            double entryRisk;
            try {
                entryRisk = jo.get("entry_risk").getAsDouble();
            } catch (Exception ee) {
                entryRisk = Double.NaN;
            }
            String profitTarget;
            Double profitTargetDbl;
            try {
                profitTarget = formatBigDecimal(jo.get("profit_target").getAsBigDecimal());
                profitTargetDbl = jo.get("profit_target").getAsDouble();
            } catch (Exception ee) {
                profitTarget = null;
                profitTargetDbl = null;
            }
            String stopLoss;
            Double stopLossDbl;
            try {
                stopLoss = formatBigDecimal(jo.get("stop_loss").getAsBigDecimal());
                stopLossDbl = jo.get("stop_loss").getAsDouble();
            } catch (Exception ee) {
                stopLoss = null;
                stopLossDbl = null;
            }

            Double lastClose;
            try {
                lastClose = jo.get("last_close").getAsDouble();
            } catch (Exception ee) {
                lastClose = null;
            }

            // Currently maximum one entry and maximum one exit are supported.
            String entryStr = "";
            String exitStr = "";
            String contractRiskStr = "";

            for (int ii = 0; ii < ja.size(); ++ii) {
                JsonObject jorder = ja.get(ii).getAsJsonObject();

                switch (jorder.get("type").getAsString()) {
                case "EXIT_LONG_STOP":
                    exitStr = "Exit long at stop " + formatBigDecimal(jorder.get("stop_price").getAsBigDecimal())
                            + ".";
                    signal += " " + exitStr;
                    break;

                case "EXIT_SHORT_STOP":
                    exitStr = "Exit short at stop " + formatBigDecimal(jorder.get("stop_price").getAsBigDecimal())
                            + ".";
                    signal += " " + exitStr;
                    break;

                case "ENTER_LONG":
                    if (!Double.isNaN(entryRisk)) {
                        entryStr = String.format("Enter long at open. Contract risk is %s.",
                                formatDouble(entryRisk, 0, 0));
                        signal += " " + entryStr;
                    } else {
                        entryStr = "Enter long at open.";
                        signal += " " + entryStr;
                    }
                    break;

                case "ENTER_SHORT":
                    if (!Double.isNaN(entryRisk)) {
                        entryStr = String.format("Enter short at open. Contract risk is %s.",
                                formatDouble(entryRisk, 0, 0));
                        signal += " " + entryStr;
                    } else {
                        entryStr = "Enter short at open.";
                        signal += " " + entryStr;
                    }
                    break;

                case "ENTER_LONG_STOP":
                    position = jorder.get("quantity").getAsLong();
                    entryStr = String.format("Enter long [%d] at stop %s [%s%%].", position,
                            formatBigDecimal(jorder.get("stop_price").getAsBigDecimal()),
                            formatPercentage(jorder.get("stop_price").getAsDouble() / lastClose * 100 - 100));
                    signal += " " + entryStr;
                    if (!Double.isNaN(entryRisk)) {
                        contractRiskStr = String.format(" Contract risk is %s.", formatDouble(entryRisk, 0, 0));
                        signal += " " + contractRiskStr;
                    }
                    break;

                case "ENTER_LONG_STOP_LIMIT":
                    position = jorder.get("quantity").getAsLong();
                    entryStr = String.format("Enter long [%d] at limit %s, stop at %s [%s%%].", position,
                            formatBigDecimal(jorder.get("limit_price").getAsBigDecimal()),
                            formatBigDecimal(jorder.get("stop_price").getAsBigDecimal()),
                            formatPercentage(jorder.get("stop_price").getAsDouble() / lastClose * 100 - 100));
                    signal += " " + entryStr;
                    if (!Double.isNaN(entryRisk)) {
                        contractRiskStr = String.format(" Contract risk is %s.", formatDouble(entryRisk, 0, 0));
                        signal += contractRiskStr;
                    }
                    break;

                case "ENTER_SHORT_STOP":
                    // signal += " Enter short at stop " + formatBigDecimal(jorder.get("stop_price").getAsBigDecimal()) + ".";
                    position = jorder.get("quantity").getAsLong();
                    entryStr = String.format("Enter short [%d] at stop %s [%s%%].", Math.abs(position),
                            formatBigDecimal(jorder.get("stop_price").getAsBigDecimal()),
                            formatPercentage(jorder.get("stop_price").getAsDouble() / lastClose * 100 - 100));
                    signal += " " + entryStr;
                    if (!Double.isNaN(entryRisk)) {
                        contractRiskStr = String.format(" Contract risk is %s.", formatDouble(entryRisk, 0, 0));
                        signal += " " + contractRiskStr;
                    }
                    break;

                case "ENTER_SHORT_STOP_LIMIT":
                    position = jorder.get("quantity").getAsLong();
                    entryStr = String.format("Enter short [%d] at limit %s, stop at %s [%s%%].", Math.abs(position),
                            formatBigDecimal(jorder.get("limit_price").getAsBigDecimal()),
                            formatBigDecimal(jorder.get("stop_price").getAsBigDecimal()),
                            formatPercentage(jorder.get("stop_price").getAsDouble() / lastClose * 100 - 100));
                    signal += " " + entryStr;
                    if (!Double.isNaN(entryRisk)) {
                        contractRiskStr = String.format(" Contract risk is %s.", formatDouble(entryRisk, 0, 0));
                        signal += " " + contractRiskStr;
                    }
                    break;

                case "EXIT_LONG":
                    exitStr = "Exit long at open.";
                    signal += " " + exitStr;
                    break;

                case "EXIT_SHORT":
                    exitStr = "Exit short at open.";
                    signal += " " + exitStr;
                    break;

                case "EXIT_SHORT_STOP_LIMIT":
                    exitStr = "Exit short at limit " + formatBigDecimal(jorder.get("limit_price").getAsBigDecimal())
                            + ", stop at " + formatBigDecimal(jorder.get("stop_price").getAsBigDecimal()) + " ["
                            + formatPercentage(jorder.get("stop_price").getAsDouble() / lastClose * 100 - 100)
                            + "%]" + ".";
                    signal += " " + exitStr;
                    break;

                case "EXIT_LONG_STOP_LIMIT":
                    exitStr = "Exit long at limit " + formatBigDecimal(jorder.get("limit_price").getAsBigDecimal())
                            + ", stop at " + formatBigDecimal(jorder.get("stop_price").getAsBigDecimal()) + " ["
                            + formatPercentage(jorder.get("stop_price").getAsDouble() / lastClose * 100 - 100)
                            + "%]" + ".";
                    signal += " " + exitStr;
                    break;
                }
                hasOrder = true;
            }

            String lastCloseStr = "Last close at " + formatBigDecimal(jo.get("last_close").getAsBigDecimal()) + ".";
            String stopLossStr = "";
            String profitTargetStr = "";

            if (hasOrder) {
                signal += " " + lastCloseStr;
            }

            if (stopLoss != null) {
                stopLossStr = "Stop loss at " + stopLoss;
                if (lastClose != null && stopLossDbl != null) {
                    stopLossStr += " [" + formatPercentage(stopLossDbl / lastClose * 100 - 100) + "%]";
                }
                stopLossStr += ".";
                signal += " " + stopLossStr;
            }

            if (profitTarget != null) {
                profitTargetStr = "Profit target at about " + profitTarget;
                if (profitTargetDbl != null && lastClose != null) {
                    profitTargetStr += " [" + formatPercentage(profitTargetDbl / lastClose * 100 - 100) + "%]";
                }
                profitTargetStr += ".";
                signal += " " + profitTargetStr;
            }

            if (printer != null) {
                printer.print(exitStr);
                printer.print(entryStr);
                printer.print(contractRiskStr);
                printer.print(lastCloseStr);
                printer.print(stopLossStr);
                printer.print(profitTargetStr);
                printer.println();
            }

            result.add(InstrumentText.make(name, symbol, contract, signal));
        }

        rs.close();
        pstmt.close();

        if (printer != null)
            printer.flush();

        return result;
    }

    private static final String STRATEGY_ORDER_QUERY = " select c.id as cid, c.name as cname, i.comment as name, coalesce(ivar.symbol, spos.symbol) as actual_symbol, "
            + "     spos.position as position, strftime('%Y-%m-%d', spos.ts/1000.0, 'unixepoch') as date, spos.last_close as close, "
            + "     spos.last_ts as close_date, "
            + "     spos.details AS details, strftime('%Y%m',i.current_contract/1000.0,'unixepoch') as current_contract, "
            + "     strftime('%Y%m',i.next_contract/1000.0,'unixepoch') as next_contract, i.trading_days as days, "
            + "     ie.exchange as exchange, i.type as type, "
            + "     strftime('%Y%m',i.current_contract2/1000.0,'unixepoch') as current_contract2, i.roll_today as roll_today "
            + " from strategy_positions spos " + " inner join strategies s on s.id = spos.strategy_id "
            + " inner join instrument i on i.symbol = spos.symbol and i.provider = 'csi' "
            + " left join instrument_variation ivar on spos.symbol = ivar.original_symbol and ivar.original_provider = 'csi' "
            + " left join instrument_visiable iv on iv.instrument_id = i.id "
            + " left join categories c on iv.categories_id = c.id "
            + " left join instrument_exchange ie on coalesce(ivar.symbol, spos.symbol) = ie.symbol "
            + " WHERE s.name = ? AND strftime('%Y-%m-%d', spos.last_ts/1000.0, 'unixepoch') = strftime('%Y-%m-%d', ?/1000.0, 'unixepoch') "
            + " ORDER BY cid, iv.ord";

    private static final String STRATEGY_ORDER_QUERY_MYSQL = " select c.id as cid, c.name as cname, i.comment as name, coalesce(ivar.symbol, spos.symbol) as actual_symbol, "
            + "     spos.position as position, date_format(spos.ts, '%Y-%m-%d') as date, spos.last_close as close, "
            + "     spos.last_ts as close_date, "
            + "     spos.details AS details, date_format(i.current_contract,'%Y%m') as current_contract, "
            + "     date_format(i.next_contract,'%Y%m') as next_contract, i.trading_days as days, "
            + "     ie.exchange as exchange, i.type as type, "
            + "     date_format(i.current_contract2,'%Y%m') as current_contract2, i.roll_today as roll_today "
            + " from strategy_positions spos " + " inner join strategies s on s.id = spos.strategy_id "
            + " inner join instrument i on i.symbol = spos.symbol and i.provider = 'csi' "
            + " left join instrument_variation ivar on spos.symbol = ivar.original_symbol and ivar.original_provider = 'csi' "
            + " left join instrument_visiable iv on iv.instrument_id = i.id "
            + " left join categories c on iv.categories_id = c.id "
            + " left join instrument_exchange ie on coalesce(ivar.symbol, spos.symbol) = ie.symbol "
            + " WHERE s.name = ? AND DATE(spos.last_ts) = DATE(?) " + " ORDER BY cid, iv.ord";

    private static final String[] CSV_HEADER = { "Action", "Quantity", "Symbol", "SecType",
            "LastTradingDayOrContractMonth", "Exchange", "OrderType", "LmtPrice", "AuxPrice" };

    public static void buildOrdersCsv(String dbUrl, String strategy, LocalDate date, String csvPath)
            throws Exception {
        Connection con = DriverManager.getConnection(dbUrl);

        CSVPrinter printer = null;
        if (csvPath != null) {
            // Add withHeader for headers
            printer = CSVFormat.DEFAULT.withDelimiter(',').withHeader(CSV_HEADER)
                    .print(new BufferedWriter(new FileWriter(csvPath)));
        }

        int rollMethod = 2;

        DatabaseMetaData dmd = con.getMetaData();
        String driverName = dmd.getDriverName();
        String query = "";
        if (driverName.startsWith("MySQL")) {
            query = STRATEGY_ORDER_QUERY_MYSQL;
        } else {
            query = STRATEGY_ORDER_QUERY;
        }

        PreparedStatement pstmt = con.prepareStatement(query);
        pstmt.setString(1, strategy);
        pstmt.setTimestamp(2, Timestamp.valueOf(date.atStartOfDay()));
        ResultSet rs = pstmt.executeQuery();
        while (rs.next()) {
            JsonObject jo = new Gson().fromJson(rs.getString(9), JsonObject.class);
            JsonArray ja = jo.get("orders").getAsJsonArray();

            int ndays = rs.getInt(12);
            String contract = "";
            if (rollMethod == 1) {
                if (ndays > 1) {
                    contract = rs.getString(10);
                } else {
                    contract = rs.getString(11);
                }
            } else if (rollMethod == 2) {
                contract = rs.getString(15);
            }

            for (int ii = 0; ii < ja.size(); ++ii) {
                JsonObject jorder = ja.get(ii).getAsJsonObject();

                switch (jorder.get("type").getAsString()) {
                case "EXIT_LONG_STOP":
                    // Action
                    printer.print("SELL");
                    // Quantity
                    printer.print(jorder.get("quantity").getAsLong());
                    // Symbol
                    printer.print(rs.getString(4));
                    // SecType
                    printer.print(rs.getString(14));
                    // LastTradingDayOrContractMonth
                    printer.print(contract);
                    // Exchange
                    printer.print(rs.getString(13));
                    // OrderType
                    printer.print("STP");
                    // LmtPrice
                    printer.print("");
                    // AuxPrice
                    printer.print(formatOrderPrice(jorder.get("stop_price").getAsBigDecimal()));
                    printer.println();
                    break;

                case "EXIT_SHORT_STOP":
                    // Action
                    printer.print("BUY");
                    // Quantity
                    printer.print(jorder.get("quantity").getAsLong());
                    // Symbol
                    printer.print(rs.getString(4));
                    // SecType
                    printer.print(rs.getString(14));
                    // LastTradingDayOrContractMonth
                    printer.print(contract);
                    // Exchange
                    printer.print(rs.getString(13));
                    // OrderType
                    printer.print("STP");
                    // LmtPrice
                    printer.print("");
                    // AuxPrice
                    printer.print(formatOrderPrice(jorder.get("stop_price").getAsBigDecimal()));
                    printer.println();
                    break;

                case "ENTER_LONG":
                    // Action
                    printer.print("BUY");
                    // Quantity
                    printer.print(jorder.get("quantity").getAsLong());
                    // Symbol
                    printer.print(rs.getString(4));
                    // SecType
                    printer.print(rs.getString(14));
                    // LastTradingDayOrContractMonth
                    printer.print(contract);
                    // Exchange
                    printer.print(rs.getString(13));
                    // OrderType
                    printer.print("MKT");
                    // LmtPrice
                    printer.print("");
                    // AuxPrice
                    printer.print("");
                    printer.println();
                    break;

                case "ENTER_SHORT":
                    // Action
                    printer.print("SELL");
                    // Quantity
                    printer.print(jorder.get("quantity").getAsLong());
                    // Symbol
                    printer.print(rs.getString(4));
                    // SecType
                    printer.print(rs.getString(14));
                    // LastTradingDayOrContractMonth
                    printer.print(contract);
                    // Exchange
                    printer.print(rs.getString(13));
                    // OrderType
                    printer.print("MKT");
                    // LmtPrice
                    printer.print("");
                    // AuxPrice
                    printer.print("");
                    printer.println();
                    break;

                case "ENTER_LONG_STOP":
                    // Action
                    printer.print("BUY");
                    // Quantity
                    printer.print(jorder.get("quantity").getAsLong());
                    // Symbol
                    printer.print(rs.getString(4));
                    // SecType
                    printer.print(rs.getString(14));
                    // LastTradingDayOrContractMonth
                    printer.print(contract);
                    // Exchange
                    printer.print(rs.getString(13));
                    // OrderType
                    printer.print("STP");
                    // LmtPrice
                    printer.print("");
                    // AuxPrice
                    printer.print(formatOrderPrice(jorder.get("stop_price").getAsBigDecimal()));
                    printer.println();
                    break;

                case "ENTER_LONG_STOP_LIMIT":
                    // Action
                    printer.print("BUY");
                    // Quantity
                    printer.print(jorder.get("quantity").getAsLong());
                    // Symbol
                    printer.print(rs.getString(4));
                    // SecType
                    printer.print(rs.getString(14));
                    // LastTradingDayOrContractMonth
                    printer.print(contract);
                    // Exchange
                    printer.print(rs.getString(13));
                    // OrderType
                    printer.print("STP LMT");
                    // LmtPrice
                    printer.print(formatOrderPrice(jorder.get("limit_price").getAsBigDecimal()));
                    // AuxPrice
                    printer.print(formatOrderPrice(jorder.get("stop_price").getAsBigDecimal()));
                    printer.println();
                    break;

                case "ENTER_SHORT_STOP":
                    // Action
                    printer.print("SELL");
                    // Quantity
                    printer.print(jorder.get("quantity").getAsLong());
                    // Symbol
                    printer.print(rs.getString(4));
                    // SecType
                    printer.print(rs.getString(14));
                    // LastTradingDayOrContractMonth
                    printer.print(contract);
                    // Exchange
                    printer.print(rs.getString(13));
                    // OrderType
                    printer.print("STP");
                    // LmtPrice
                    printer.print("");
                    // AuxPrice
                    printer.print(formatOrderPrice(jorder.get("stop_price").getAsBigDecimal()));
                    printer.println();
                    break;

                case "ENTER_SHORT_STOP_LIMIT":
                    // Action
                    printer.print("SELL");
                    // Quantity
                    printer.print(jorder.get("quantity").getAsLong());
                    // Symbol
                    printer.print(rs.getString(4));
                    // SecType
                    printer.print(rs.getString(14));
                    // LastTradingDayOrContractMonth
                    printer.print(contract);
                    // Exchange
                    printer.print(rs.getString(13));
                    // OrderType
                    printer.print("STP LMT");
                    // LmtPrice
                    printer.print(formatOrderPrice(jorder.get("limit_price").getAsBigDecimal()));
                    // AuxPrice
                    printer.print(formatOrderPrice(jorder.get("stop_price").getAsBigDecimal()));
                    printer.println();
                    break;

                case "EXIT_LONG":
                    // Action
                    printer.print("SELL");
                    // Quantity
                    printer.print(jorder.get("quantity").getAsLong());
                    // Symbol
                    printer.print(rs.getString(4));
                    // SecType
                    printer.print(rs.getString(14));
                    // LastTradingDayOrContractMonth
                    printer.print(contract);
                    // Exchange
                    printer.print(rs.getString(13));
                    // OrderType
                    printer.print("MKT");
                    // LmtPrice
                    printer.print("");
                    // AuxPrice
                    printer.print("");
                    printer.println();
                    break;

                case "EXIT_SHORT":
                    // Action
                    printer.print("BUY");
                    // Quantity
                    printer.print(jorder.get("quantity").getAsLong());
                    // Symbol
                    printer.print(rs.getString(4));
                    // SecType
                    printer.print(rs.getString(14));
                    // LastTradingDayOrContractMonth
                    printer.print(contract);
                    // Exchange
                    printer.print(rs.getString(13));
                    // OrderType
                    printer.print("MKT");
                    // LmtPrice
                    printer.print("");
                    // AuxPrice
                    printer.print("");
                    printer.println();
                    break;

                case "EXIT_SHORT_STOP_LIMIT":
                    // Action
                    printer.print("BUY");
                    // Quantity
                    printer.print(jorder.get("quantity").getAsLong());
                    // Symbol
                    printer.print(rs.getString(4));
                    // SecType
                    printer.print(rs.getString(14));
                    // LastTradingDayOrContractMonth
                    printer.print(contract);
                    // Exchange
                    printer.print(rs.getString(13));
                    // OrderType
                    printer.print("STP LMT");
                    // LmtPrice
                    printer.print(formatOrderPrice(jorder.get("limit_price").getAsBigDecimal()));
                    // AuxPrice
                    printer.print(formatOrderPrice(jorder.get("stop_price").getAsBigDecimal()));
                    printer.println();
                    break;

                case "EXIT_LONG_STOP_LIMIT":
                    // Action
                    printer.print("SELL");
                    // Quantity
                    printer.print(jorder.get("quantity").getAsLong());
                    // Symbol
                    printer.print(rs.getString(4));
                    // SecType
                    printer.print(rs.getString(14));
                    // LastTradingDayOrContractMonth
                    printer.print(contract);
                    // Exchange
                    printer.print(rs.getString(13));
                    // OrderType
                    printer.print("STP LMT");
                    // LmtPrice
                    printer.print(formatOrderPrice(jorder.get("limit_price").getAsBigDecimal()));
                    // AuxPrice
                    printer.print(formatOrderPrice(jorder.get("stop_price").getAsBigDecimal()));
                    printer.println();
                    break;
                }
            }

            if (printer != null)
                printer.flush();
        }
    }

    static private String formatBigDecimal(BigDecimal bd, int minPrecision, int maxPrecision) {
        bd = bd.setScale(maxPrecision, RoundingMode.HALF_UP).stripTrailingZeros();
        int scale = bd.scale() <= minPrecision ? minPrecision : bd.scale();
        return String.format("%,." + Integer.toString(scale) + "f", bd);
    }

    static private String formatBigDecimal(BigDecimal bd) {
        return formatBigDecimal(bd, 2, 7);
    }

    static private String formatDouble(double dd, int minPrecision, int maxPrecision) {
        BigDecimal bd = new BigDecimal(dd, MathContext.DECIMAL128);
        bd = bd.setScale(maxPrecision, RoundingMode.HALF_UP);
        return formatBigDecimal(bd);
    }

    static private String formatDouble(double dd) {
        return formatDouble(dd, 2, 7);
    }

    static private String formatPercentage(double dd) {
        return formatDouble(dd, 2, 2);
    }

    static private String formatOrderPrice(BigDecimal bd) {
        bd = bd.setScale(7, RoundingMode.HALF_UP).stripTrailingZeros();
        int scale = bd.scale() <= 2 ? 2 : bd.scale();
        return String.format("%." + Integer.toString(scale) + "f", bd);
    }
}