# HG changeset patch
# User Marcus Williford <mwilliford@gmail.com>
# Date 1357729599 28800
# Branch CL
# Node ID a48620581b31cef73b78f74201e9749d3dab7e97
# Parent  a4c433f149b6de7a99014882312cfe19f52f743c
adding CL src files

diff -r a4c433f149b6 -r a48620581b31 source/com/jbooktrader/platform/test/NYMEXMostLiquidTest.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/source/com/jbooktrader/platform/test/NYMEXMostLiquidTest.java	Wed Jan 09 03:06:39 2013 -0800
@@ -0,0 +1,105 @@
+package com.jbooktrader.platform.test;
+
+import com.jbooktrader.platform.util.NYMEXMostLiquid;
+
+import java.util.Calendar;
+import static org.junit.Assert.*;
+import org.junit.*;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: marcus
+ * Date: 1/9/13
+ * Time: 12:31 AM
+ * To change this template use File | Settings | File Templates.
+ */
+public class NYMEXMostLiquidTest {
+
+    @Test
+    public void backupToBusinessDay1() {
+        Calendar aSaturday = Calendar.getInstance();
+        aSaturday.set(Calendar.YEAR,2013);
+        aSaturday.set(Calendar.MONTH,Calendar.JANUARY);
+        aSaturday.set(Calendar.DATE,5);
+
+        assert(aSaturday.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY);
+        NYMEXMostLiquid.backupToBusinessDay(aSaturday); // should back up to Friday
+        assert(aSaturday.get(Calendar.DAY_OF_WEEK) == Calendar.FRIDAY);
+        NYMEXMostLiquid.backupToBusinessDay(aSaturday);
+        assert(aSaturday.get(Calendar.DAY_OF_WEEK) == Calendar.FRIDAY);  // should still be Friday
+
+    }
+
+    // http://www.cmegroup.com/trading/energy/crude-oil/light-sweet-crude_product_calendar_futures.html
+    @Test
+    public void getExpireDayForMonthYearTest() {
+        // test some real NYMEX dates from the CL (Light Sweet Crude index futures
+
+        int janExpire = NYMEXMostLiquid.getExpireDateForMonthYear(1,2013);  // actually this is called the Feb delivery future, exprires in Jan though
+        assert(janExpire == 22);
+        int febExpire = NYMEXMostLiquid.getExpireDateForMonthYear(2,2013);
+        assert(febExpire == 20);
+        int marExpire = NYMEXMostLiquid.getExpireDateForMonthYear(3,2013);
+        assert(marExpire == 20);
+        int aprExpire = NYMEXMostLiquid.getExpireDateForMonthYear(4,2013);
+        assert(aprExpire == 22);
+        int mayExpire = NYMEXMostLiquid.getExpireDateForMonthYear(5,2013);
+        assert(mayExpire == 21);
+        int junExpire = NYMEXMostLiquid.getExpireDateForMonthYear(6,2013);
+        assert(junExpire == 20);
+        int julExpire = NYMEXMostLiquid.getExpireDateForMonthYear(7,2013);
+        assert(julExpire == 22);
+
+    }
+
+    @Test
+    public void getMostLiquidNymexExpiryTest1() {
+        Calendar mydate = Calendar.getInstance();
+        mydate.set(Calendar.YEAR, 2013);
+        mydate.set(Calendar.MONTH, Calendar.JANUARY);
+        mydate.set(Calendar.DATE, 5);
+
+        String expiry = NYMEXMostLiquid.getMostLiquidExpiry(mydate);
+        assertTrue("expiration of contract not correct", expiry.equals("201302"));  // note, this is called the Feburary Contract, but expries on Jan 22
+
+    }
+
+    @Test
+    public void getMostLiquidNymexExpiryTestDecRolltoNewyear() {
+        Calendar mydate = Calendar.getInstance();
+        mydate.set(Calendar.YEAR, 2012);
+        mydate.set(Calendar.MONTH, Calendar.DECEMBER);
+        mydate.set(Calendar.DATE, 18);
+
+        String expiry = NYMEXMostLiquid.getMostLiquidExpiry(mydate);
+        assertEquals("expiration of contract not correct", "201302",expiry);  // note, this is called the Feburary Contract, but expries on Jan 22
+
+    }
+
+    @Test
+    public void getMostLiquidNymexExpiryTestDecnoRollover() {
+        Calendar mydate = Calendar.getInstance();
+        mydate.set(Calendar.YEAR, 2012);
+        mydate.set(Calendar.MONTH, Calendar.DECEMBER);
+        mydate.set(Calendar.DATE, 8);
+
+        String expiry = NYMEXMostLiquid.getMostLiquidExpiry(mydate);
+        assertEquals("expiration of contract not correct", "201301",expiry);  // note, this is called the Feburary Contract, but expries on Jan 22
+
+    }
+
+    @Test
+    public void getMostLiquidNymexExpiryTestTooClose() {
+        Calendar mydate = Calendar.getInstance();
+        mydate.set(Calendar.YEAR, 2013);
+        mydate.set(Calendar.MONTH, Calendar.JANUARY);
+        mydate.set(Calendar.DATE, 22);
+
+        String expiry = NYMEXMostLiquid.getMostLiquidExpiry(mydate);
+        assertEquals("expiration of contract not correct", "201303",expiry);  // note, this is called the Feburary Contract, but expries on Jan 22
+
+    }
+
+}
+
+
diff -r a4c433f149b6 -r a48620581b31 source/com/jbooktrader/platform/util/ContractFactory.java
--- a/source/com/jbooktrader/platform/util/ContractFactory.java	Mon Jan 09 17:41:25 2012 -0500
+++ b/source/com/jbooktrader/platform/util/ContractFactory.java	Wed Jan 09 03:06:39 2013 -0800
@@ -39,6 +39,10 @@
         return makeFutureContract(symbol, exchange, MostLiquidContract.getMostLiquid());
     }
 
+    public static Contract makeNYMEXFutureContract(String symbol,String exchange) {
+        return makeFutureContract(symbol, exchange, NYMEXMostLiquid.getMostLiquid());
+    }
+
     public static Contract makeCashContract(String symbol, String currency) {
         return makeContract(symbol, "CASH", "IDEALPRO", null, currency);
     }
diff -r a4c433f149b6 -r a48620581b31 source/com/jbooktrader/platform/util/NYMEXMostLiquid.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/source/com/jbooktrader/platform/util/NYMEXMostLiquid.java	Wed Jan 09 03:06:39 2013 -0800
@@ -0,0 +1,101 @@
+package com.jbooktrader.platform.util;
+
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: marcus
+ * Date: 1/8/13
+ * Time: 11:26 PM
+ * To change this template use File | Settings | File Templates.
+ */
+public class NYMEXMostLiquid {
+
+    public static final int VOLUME_CROSSOVER_BEFORE_EXP = 8; // in business days before expiration
+
+    /**
+     * Given a month, what is the expiration day, based on the following rule
+     * - 3 business days prior to the 25th
+     * - If the 25th falls on a weekend, 3 business days not counting this weekend
+     *
+     * - not sure about holidays yet, TBD
+     *
+     * @param month  Integer month 1-12
+     * @return day of expiration
+     */
+    public static int getExpireDateForMonthYear(int month, int year) {
+        Calendar cal = Calendar.getInstance();
+        cal.set(Calendar.MONTH,month-1);
+        cal.set(Calendar.YEAR,year);
+        cal.set(Calendar.DATE,25); // using this 25th as a rule here
+
+        // get to first non weekend day, prior to the 25th
+        backupToBusinessDay(cal);
+        // now, we should subtract 3 business days
+        for (int i = 0; i < 3; i++) {
+            backupToBusinessDay(cal);
+            cal.add(Calendar.DATE, -1);  // subtract a day, which don't be on a weekend
+        }
+
+        return cal.get(Calendar.DATE);
+
+    }
+
+    public static void backupToBusinessDay(Calendar cal) {
+        while (!isBusinessDay(cal)) {
+            cal.add(Calendar.DATE, -1);  // subtract a day
+        }
+    }
+
+    public static boolean isBusinessDay(Calendar cal) {
+        return (cal.get(Calendar.DAY_OF_WEEK) != Calendar.SATURDAY && cal.get(Calendar.DAY_OF_WEEK) != Calendar.SUNDAY);
+    }
+
+
+    public static String getMostLiquidExpiry(Calendar mydate) {
+        Calendar contract = Calendar.getInstance();
+        contract.setTime(mydate.getTime());
+
+        // start by selecting current month, and see if it is ok
+        int myMonth = mydate.get(Calendar.MONTH) + 1;
+        int myYear = mydate.get(Calendar.YEAR);
+        int dateExp = getExpireDateForMonthYear(myMonth,myYear);
+
+        Calendar cutoffDate = Calendar.getInstance();
+        cutoffDate.set(Calendar.YEAR,mydate.get(Calendar.YEAR));
+        cutoffDate.set(Calendar.MONTH,mydate.get(Calendar.MONTH));
+        cutoffDate.set(Calendar.DATE,dateExp);
+
+        for (int i = 0; i < VOLUME_CROSSOVER_BEFORE_EXP; i++) {
+            backupToBusinessDay(cutoffDate);
+            cutoffDate.add(Calendar.DATE, -1);
+        }
+
+        // check to see if we are far enough away to use this month
+
+        if (mydate.compareTo(cutoffDate) < 0) {  // we can use this month
+            contract.set(Calendar.DATE,dateExp);
+        } else {
+            // need to use next months
+            contract.add(Calendar.MONTH, 1); // next month
+            dateExp = getExpireDateForMonthYear(    // replace date with exp date for that month
+                    contract.get(Calendar.MONTH)+1,
+                    contract.get(Calendar.YEAR)
+            );
+            contract.set(Calendar.DATE,dateExp);
+        }
+
+        // return contract as a string as required by tws
+        // note, nominal feb contract would have expire date in Jan, and we think tws expects jan expire date for Feb nominal contract
+        contract.add(Calendar.MONTH,1);  // contract is called by the month after's name for NYMEX
+        // update:  we need to send normal month info, per this link: http://www.interactivebrokers.com/en/trading/expirationLabel.html
+        SimpleDateFormat df = new SimpleDateFormat("yyyyMM");
+        return df.format(contract.getTime());
+
+    }
+
+    public static String getMostLiquid() {
+        return getMostLiquidExpiry(Calendar.getInstance());
+    }
+}
diff -r a4c433f149b6 -r a48620581b31 source/com/jbooktrader/strategy/SampleCL.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/source/com/jbooktrader/strategy/SampleCL.java	Wed Jan 09 03:06:39 2013 -0800
@@ -0,0 +1,70 @@
+package com.jbooktrader.strategy;
+
+import com.jbooktrader.indicator.balance.BalanceVelocity;
+import com.jbooktrader.indicator.price.PriceKalman;
+import com.jbooktrader.indicator.price.PriceVelocity;
+import com.jbooktrader.platform.indicator.Indicator;
+import com.jbooktrader.platform.model.JBookTraderException;
+import com.jbooktrader.platform.optimizer.StrategyParams;
+import com.jbooktrader.strategy.base.StrategyCL;
+import com.jbooktrader.strategy.base.StrategyES;
+
+
+/**
+ *
+ */
+public class SampleCL extends StrategyCL {
+
+    // Technical indicators
+    private Indicator balanceVelocityInd, priceVelocityInd, kalmanInd;
+
+    // Strategy parameters names
+    private static final String PERIOD = "Period";
+    private static final String SCALE = "Scale";
+    private static final String ENTRY = "Entry";
+    private static final String EXIT = "Exit";
+    private static final String NOISE = "Noise";
+
+    // Strategy parameters values
+    private final int entry, exit, scale, noise;
+
+
+    public SampleCL(StrategyParams optimizationParams) throws JBookTraderException {
+        super(optimizationParams);
+
+        entry = getParam(ENTRY);
+        exit = getParam(EXIT);
+        scale = getParam(SCALE);
+        noise = getParam(NOISE);
+    }
+
+    @Override
+    public void setParams() {
+        addParam(PERIOD, 2200, 3600, 5, 3515);
+        addParam(SCALE, 5, 25, 1, 25);
+        addParam(ENTRY, 55, 120, 1, 95);
+        addParam(EXIT, -50, 0, 1, 0);
+        addParam(NOISE, 1, 50 , 1 , 2);
+    }
+
+    @Override
+    public void setIndicators() {
+        balanceVelocityInd = addIndicator(new BalanceVelocity(1, getParam(PERIOD)));
+        priceVelocityInd = addIndicator(new PriceVelocity(1, getParam(PERIOD)));
+        kalmanInd = addIndicator(new PriceKalman(getParam(NOISE)));
+
+    }
+
+    @Override
+    public void onBookSnapshot() {
+        double balanceVelocity = balanceVelocityInd.getValue();
+        double priceVelocity = priceVelocityInd.getValue();
+
+        double force = balanceVelocity - scale * priceVelocity;
+        if (force >= entry && balanceVelocity > 0 && priceVelocity < 0) {
+            setPosition(1);
+        } else if (force <= -exit) {
+            setPosition(0);
+        }
+    }
+}
\ No newline at end of file
diff -r a4c433f149b6 -r a48620581b31 source/com/jbooktrader/strategy/base/StrategyCL.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/source/com/jbooktrader/strategy/base/StrategyCL.java	Wed Jan 09 03:06:39 2013 -0800
@@ -0,0 +1,36 @@
+package com.jbooktrader.strategy.base;
+
+import com.ib.client.Contract;
+import com.jbooktrader.platform.commission.Commission;
+import com.jbooktrader.platform.commission.CommissionFactory;
+import com.jbooktrader.platform.model.JBookTraderException;
+import com.jbooktrader.platform.optimizer.StrategyParams;
+import com.jbooktrader.platform.schedule.TradingSchedule;
+import com.jbooktrader.platform.strategy.Strategy;
+import com.jbooktrader.platform.util.ContractFactory;
+
+/**
+ *
+ */
+public abstract class StrategyCL extends Strategy {
+    /*
+    * MARGIN REQUIREMENTS for CL: GLOBEX as of 8-Jan-2013
+    * Source: http://www.interactivebrokers.com/en/index.php?f=margin&p=fut
+    *
+    * Initial Intra-day: $3,188
+    * Intra-day Maintenance: $2,550
+    * Initial Overnight: $6,375
+    * Overnight Maintenance: $5,100
+    */
+    protected StrategyCL(StrategyParams optimizationParams) throws JBookTraderException {
+        super(optimizationParams);
+        // Specify the contract to trade
+        Contract contract = ContractFactory.makeNYMEXFutureContract("CL", "NYMEX");
+        // Define trading schedule
+        TradingSchedule tradingSchedule = new TradingSchedule("10:35", "14:55", "America/New_York");
+        int multiplier = 1000;// contract 1000 barrels
+        double bidAskSpread = 0.01; // prevalent spread between best bid and best ask
+        Commission commission = CommissionFactory.getBundledNorthAmericaFutureCommission();
+        setStrategy(contract, tradingSchedule, multiplier, commission, bidAskSpread);
+    }
+}
