Created
March 4, 2023 20:51
-
-
Save Kurry/cc81dc9066ad194694929017c5212dff to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package FocusPackage; | |
import com.assylias.jbloomberg.DataChangeEvent; | |
import com.assylias.jbloomberg.DefaultBloombergSession; | |
import com.assylias.jbloomberg.IntradayStudyData; | |
import com.assylias.jbloomberg.IntradayStudyField; | |
import com.assylias.jbloomberg.IntradayStudyRequestBuilder; | |
import com.assylias.jbloomberg.RealtimeField; | |
import com.assylias.jbloomberg.TypedObject; | |
import com.bloomberglp.blpapi.CorrelationID; | |
import com.bloomberglp.blpapi.Element; | |
import com.bloomberglp.blpapi.Request; | |
import com.bloomberglp.blpapi.SessionOptions; | |
import com.bloomberglp.blpapi.Subscription; | |
import com.bloomberglp.blpapi.SubscriptionList; | |
import com.google.common.collect.HashBasedTable; | |
import com.google.common.collect.Table; | |
import com.portlandhouse.trading.AlgorithmType; | |
import com.portlandhouse.trading.LimitPriceCalculator; | |
import com.portlandhouse.trading.LimitPriceCalculatorBuilder; | |
import static com.portlandhouse.trading.TargetPriceType.ARRIVAL; | |
import static com.portlandhouse.trading.TargetPriceType.LAST; | |
import com.portlandhouse.trading.TradeSideType; | |
import java.awt.Color; | |
import java.awt.GridBagConstraints; | |
import java.awt.event.ActionListener; | |
import javax.swing.Timer; | |
import java.awt.event.ActionEvent; | |
import javax.swing.JFrame; | |
import javax.swing.JLabel; | |
import javax.swing.JPanel; | |
import java.awt.GridBagLayout; | |
import java.awt.Insets; | |
import java.awt.Rectangle; | |
import java.awt.event.WindowAdapter; | |
import java.awt.event.WindowEvent; | |
import java.io.IOException; | |
import java.lang.ref.WeakReference; | |
import java.text.DecimalFormat; | |
import java.text.NumberFormat; | |
import java.text.ParseException; | |
import java.util.ArrayList; | |
import java.util.List; | |
import java.util.logging.Level; | |
import java.util.logging.Logger; | |
import javax.swing.ImageIcon; | |
import javax.swing.JScrollPane; | |
import java.util.stream.IntStream; | |
import java.text.SimpleDateFormat; | |
import java.time.Duration; | |
import java.time.LocalDate; | |
import java.time.LocalDateTime; | |
import java.time.LocalTime; | |
import java.time.OffsetDateTime; | |
import java.time.format.DateTimeFormatter; | |
import java.time.format.FormatStyle; | |
import java.util.Arrays; | |
import java.util.Calendar; | |
import java.util.Collections; | |
import java.util.Comparator; | |
import java.util.Date; | |
import java.util.GregorianCalendar; | |
import java.util.HashMap; | |
import java.util.HashSet; | |
import java.util.Set; | |
import java.util.Map; | |
import static java.util.Map.entry; | |
import java.util.concurrent.ArrayBlockingQueue; | |
import java.util.concurrent.CompletableFuture; | |
import java.util.concurrent.ConcurrentHashMap; | |
import java.util.concurrent.atomic.AtomicInteger; | |
import java.util.prefs.Preferences; | |
import javax.swing.BorderFactory; | |
import javax.swing.JCheckBox; | |
import javax.swing.border.MatteBorder; | |
import org.apache.commons.math3.util.Precision; | |
public class FocusGUI extends WindowAdapter { | |
public static FocusTrigger Trigger = new FocusTrigger(); | |
public static VWAPTrigger vwapTrigger = new VWAPTrigger(); | |
public static IntradayStudyTrigger intradayStudyTrigger = new IntradayStudyTrigger(); | |
private static final Table<String, String, TypedObject> marketDataTable = HashBasedTable.create(); | |
public static ReferenceRequestTrigger referenceRequestTrigger = new ReferenceRequestTrigger(marketDataTable); | |
public static SubscriptionRequestTrigger subscriptionRequestTrigger = new SubscriptionRequestTrigger(marketDataTable); | |
private static final Logger LOGGER = Logger.getLogger("splunkLogger"); | |
public Preferences prefs = Preferences.userNodeForPackage(FocusGUI.class); | |
final String PREF_HEIGHT = "window_height"; | |
final String PREF_WIDTH = "window_width"; | |
final String PREF_X = "window_position_x"; | |
final String PREF_Y = "window_position_y"; | |
final double SLIPPAGE_BPS = 0.0025; | |
//time delays for starting the application and signing up for market data | |
// KLT: This is zero now since there is a latch in the trigger to wait for orders and routes. | |
final int initialDelayForTickers = 0; | |
final int secondDelayForFX = 15000; | |
final int screenRefresh = 1000; | |
final int studyTimerDelay = 60000; | |
//formatters | |
public DecimalFormat curr = new DecimalFormat("$#,###"); | |
public DecimalFormat shares = new DecimalFormat("#,###"); | |
public DecimalFormat perc = new DecimalFormat("#,###0'%'"); | |
public DecimalFormat chg = new DecimalFormat("#,####.##'%'"); | |
//date/time variables | |
public SimpleDateFormat tradeDateFormat = new SimpleDateFormat("yyyyMMdd"); | |
public static int tradeDate; | |
public List<Date> holidays = new ArrayList<>(); | |
public Calendar holidayDate[] = new GregorianCalendar[20]; | |
public List<Date> halfDays = new ArrayList<>(); | |
public Calendar halfDayDates[] = new GregorianCalendar[5]; | |
public SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss"); | |
public SimpleDateFormat today = new SimpleDateFormat("yyyy-MM-dd"); | |
public SimpleDateFormat todayTime = new SimpleDateFormat("HH:mm:ss"); | |
public DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); | |
public DecimalFormat px = new DecimalFormat("#,####.##"); | |
public Calendar cal = Calendar.getInstance(); | |
public Calendar prevBizDay = Calendar.getInstance(); | |
public LocalDateTime openTime[] = new LocalDateTime[1000]; | |
public LocalDateTime closeTime[] = new LocalDateTime[1000]; | |
public double sinceOpen[] = new double[1000]; | |
public double fullDay[] = new double[1000]; | |
public double toClose[] = new double[1000]; | |
public String officialOpenTime[] = new String[1000]; | |
public String openTimePlus5[] = new String[1000]; | |
public String openTimePlus10[] = new String[1000]; | |
public String closeCutoff[] = new String[1000]; | |
public String startTechStudies[] = new String[1000]; | |
public String afterOpen45[] = new String[1000]; | |
public String afterOpen60[] = new String[1000]; | |
public String afterOpen90[] = new String[1000]; | |
public String region[] = new String[1000]; | |
private int myTimerDelay; | |
private Timer myTimer; | |
private Timer studyTimer; | |
//GUI components | |
JFrame frame = new JFrame(); | |
JPanel panel = new JPanel(); | |
public static JLabel Load; | |
public static JLabel[] Header = new JLabel[1000]; | |
public static JLabel[] Total = new JLabel[1000]; | |
public static JCheckBox[] OverRide = new JCheckBox[1000]; | |
public static JCheckBox Testing; | |
public static JLabel[] SEQ = new JLabel[1000]; | |
public static JLabel[] Symbol = new JLabel[1000]; | |
public static JLabel[] Side = new JLabel[1000]; | |
public static JLabel[] Type = new JLabel[1000]; | |
public static JLabel[] LimitPx = new JLabel[1000]; | |
public static JLabel[] Idle = new JLabel[1000]; | |
public static JLabel[] Working = new JLabel[1000]; | |
public static JLabel[] Filled = new JLabel[1000]; | |
public static JLabel[] AvgPx = new JLabel[1000]; | |
public static JLabel[] Amount = new JLabel[1000]; | |
public static JLabel[] MarketValue = new JLabel[1000]; | |
public static JLabel[] RemValue = new JLabel[1000]; | |
public static JLabel[] Status = new JLabel[1000]; | |
public static JLabel[] Broker = new JLabel[1000]; | |
public static JLabel[] VwapPx = new JLabel[1000]; | |
public static JLabel[] Strategy = new JLabel[1000]; | |
public static JLabel[] ArrivalBPS = new JLabel[1000]; | |
public static JLabel[] VwapBPS = new JLabel[1000]; | |
public static JLabel[] Volume = new JLabel[1000]; | |
public static JLabel[] ArrivalPrice = new JLabel[1000]; | |
public static JLabel[] PercentFilled = new JLabel[1000]; | |
public static JLabel[] PercentTenDayADV = new JLabel[1000]; | |
public static JLabel[] LastAll = new JLabel[1000]; | |
public static JLabel[] PartRate = new JLabel[1000]; | |
public static JLabel[] LastUpdateAll = new JLabel[1000]; | |
public static JLabel[] VolumeAll = new JLabel[1000]; | |
public static JLabel[] OpenFlag = new JLabel[1000]; | |
public static JLabel[] Algo = new JLabel[1000]; | |
public static JLabel[] Trend = new JLabel[1000]; | |
public static JLabel[] RSI = new JLabel[1000]; | |
public static JLabel[] BollPercent = new JLabel[1000]; | |
public static JLabel[] ThresholdPx = new JLabel[1000]; | |
public static JLabel[] adjPDC = new JLabel[1000]; | |
//public static JLabel[] HSDPercent = new JLabel[1000]; | |
public static JLabel[] VolChg = new JLabel[1000]; | |
public static JLabel[] BASpread = new JLabel[1000]; | |
public static JLabel[] FavVolume = new JLabel[1000]; | |
public static JLabel[] GroupId = new JLabel[1000]; | |
//basket variables | |
public static ArrayList<OrderTicket> Orders = new ArrayList<>(); | |
public static ArrayList<RouteTicket> Routes = new ArrayList<>(); | |
public static String portfolioName; | |
public static int basketImbalance; | |
public static int TradeCount; | |
public static int RouteCount; | |
public static int OpenCount; | |
public static int amountTotal; | |
public static int idleTotal; | |
public static int workingTotal; | |
public static int filledTotal; | |
public static int a,k,m; | |
public static int selectAll; | |
public static double imbalance; | |
public static double remBuy; | |
public static double remSell; | |
public static double totalArrivalBps; | |
public static double totalVwapBps; | |
public static double totalMV; | |
public static double totalArrival$; | |
public static double totalVwap$; | |
public static double broadMarketChg; | |
public static double EUbroadMarketChg; | |
//order level variables | |
public static int[] sideSign = new int[1000]; | |
public static String sideLetter; | |
public static String[] ticker = new String [1000]; | |
public static String[] primaryTicker = new String [1000]; | |
public static String[] groupId = new String[1000]; | |
public static double[] newLimitPx = new double [1000]; | |
public static String[] limitString = new String [1000]; | |
public static int[] marketValue = new int [1000]; | |
public static int[] remValue = new int [1000]; | |
public static double[] bid = new double [1000]; | |
public static double[] ask = new double [1000]; | |
public static double[] last = new double [1000]; | |
public static String[] exchange = new String [1000]; | |
public static String[] currency = new String [1000]; | |
public static String[] currencyTicker = new String [1000]; | |
public static double[] fxRate = new double [1000]; | |
public static String[] algo = new String [1000]; | |
public static double[] priceIndicatedOpen = new double [1000]; | |
public static int[] volIndicatedOpen = new int [1000]; | |
public static double[] lastAll = new double [1000]; | |
public static double[] askAll = new double [1000]; | |
public static double[] bidAll = new double [1000]; | |
public static String[] lastUpdateAll = new String [1000]; | |
public static int[] volumeAll = new int [1000]; | |
public static double[] open = new double [1000]; | |
public static double[] close = new double [1000]; //rename prevClose | |
public static double[] adjPrevClose = new double [1000]; | |
public static String[] openFlag = new String [1000]; | |
public static String[] openTradeAdjust = new String [1000]; | |
public static String[] imbalanceAdjust = new String [1000]; | |
public static String[] limitAway = new String [1000]; | |
public static int[] childRouteCount = new int [1000]; | |
public static int[] openRouteCount = new int [1000]; | |
public static int[] maxRouteID = new int [1000]; | |
public static double[] avgvolume = new double [1000]; | |
public static double[] mktcap = new double [1000]; | |
public static int[] pxPosMultFactor = new int [1000]; | |
public static double[] bidAskSpread = new double [1000]; | |
public static double[] avgBidAskSpread = new double [1000]; | |
public static double[] vol10 = new double [1000]; | |
public static double[] vol120 = new double [1000]; | |
public static double[] maxVol = new double [1000]; | |
public static double[] adv10 = new double [1000]; | |
public static double[] volChg1d20d = new double [1000]; | |
public static double[] favVolume = new double [1000]; | |
public static double[] favVolumePerc = new double [1000]; | |
public static double[] hsd = new double [1000]; | |
public static double[] arrival = new double [1000]; | |
public static double[] thresholdMove = new double [1000]; | |
public static double[] thresholdPx = new double [1000]; | |
public static double[] rsi = new double [1000]; | |
public static double[] bbPerc = new double [1000]; | |
public static double[] hsdPx = new double [1000]; | |
public static double[] preMktPx = new double [1000]; | |
public static double[] volume = new double [1000]; | |
public static double[] volume20RT = new double [1000]; | |
public static String[] trend = new String [1000]; | |
public static int[] arrival$ = new int [1000]; | |
public static double[] arrivalbps = new double [1000]; | |
public static int[] vwap$ = new int [1000]; | |
public static double[] vwapbps = new double [1000]; | |
public static double[] vwap = new double [1000]; | |
public static double[] projVwap = new double [1000]; | |
public static double[] partRate = new double [1000]; | |
public static String[] pilotGroup = new String [1000]; | |
public static double[] refTickSize = new double [1000]; | |
public static double[] roundFactor = new double [1000]; | |
public static String [] MAtoday = new String [1000]; | |
public static String [] offeringPrelimFilingDate = new String [1000]; | |
public static String[] equitySplitDate = new String [1000]; | |
public static String[] divExDate = new String [1000]; | |
public static double[] divAmount = new double [1000]; | |
//route level variables | |
public static String [] routeStratType = new String [1000]; | |
public static String [] openStratType = new String [1000]; | |
public static int[] newAmount = new int [1000]; | |
public static String [] algoInput = new String [1000]; | |
public ArrayList<String> d_fields; | |
//market data variables | |
public List<String> fxFields = new ArrayList<>(); | |
public static HashSet<String> CurrArray = new HashSet<String>(); | |
private CorrelationID requestFX; | |
//vwap fields | |
public Subscription[] mktvwap_sub = new Subscription[1000]; | |
public SubscriptionList mktvwap_subscriptions = new SubscriptionList(); | |
public CorrelationID mktdata_sub_id; | |
public static boolean[] vwapSent = new boolean[1000]; | |
SimpleDateFormat dateFormat; | |
public static final Set<String> VALID_STATUSES = Set.of("WORKING", "FILLED", "PARTFILL"); | |
public static final Map<Integer, Boolean> MODIFICATION_MAP = new ConcurrentHashMap<>(); | |
public static final WstiOrderObserver WSTI_ORDER_OBSERVER = new WstiOrderObserver(marketDataTable); | |
public static final AtomicInteger START_ONCE = new AtomicInteger(); | |
public static final Map<String, String> TICKER_TO_PRIMARY_TICKER = new HashMap<>(); | |
public class SortTickers implements Comparator<OrderTicket> { //puts order_map in alpha | |
@Override | |
public int compare(OrderTicket u1, OrderTicket u2) { | |
return u1.ticker.compareTo(u2.ticker); | |
} | |
} | |
public class SortStatus implements Comparator<OrderTicket> { //sorts order_map by status | |
@Override | |
public int compare(OrderTicket u1, OrderTicket u2) { | |
return u2.status.compareTo(u1.status); | |
} | |
} | |
public class SortGroupId implements Comparator<OrderTicket> { //sorts order_map by status | |
@Override | |
public int compare(OrderTicket u1, OrderTicket u2) { | |
return u1.groupId.compareTo(u2.groupId); | |
} | |
} | |
public FocusGUI() { | |
super(); | |
int x2 = Integer.parseInt(prefs.get(PREF_X, "600")); | |
int y2 = Integer.parseInt(prefs.get(PREF_Y, "-800")); | |
frame.setBounds(x2, y2, 800, 500); //adjust below for final size //(x, y, width, height) | |
frame.setLayout(new GridBagLayout()); | |
String value = System.getProperty("portfolio", "focus"); | |
if ("focus".equals(value)) { | |
frame.setTitle("Focus Trader"); | |
} else if ("a_plus".equals(value)) { | |
frame.setTitle("A+ Trader"); | |
} else if ("pairs".equals(value)) { | |
frame.setTitle("Pairs Trader"); | |
} else if ("focus_us".equals(value)) { | |
frame.setTitle("Focus US"); | |
} else if ("ds".equals(value)) { | |
frame.setTitle("DS Portfolios"); | |
} | |
frame.setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); | |
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); | |
frame.setVisible(true); | |
frame.setAlwaysOnTop(true); | |
frame.getContentPane().setBackground(Color.BLACK); | |
Load = new JLabel(new ImageIcon(getClass().getResource("Loading.gif"))); | |
frame.add(Load); | |
frame.addWindowListener(new WindowAdapter() { | |
@Override | |
public void windowClosing(WindowEvent e) { | |
//storing preferences for window location when the app is closed | |
String position = String.valueOf(frame.getLocation()); | |
String x = position.substring(position.indexOf("x=")+2,position.indexOf("y=")-1); | |
String y = position.substring(position.indexOf("y=")+2,position.indexOf("]")); | |
Rectangle r = frame.getBounds(); | |
String h = String.valueOf(r.height); | |
String w = String.valueOf(r.width); | |
LOGGER.log(Level.FINEST, "Window closed"); | |
prefs.put(PREF_HEIGHT, h); | |
prefs.put(PREF_WIDTH, w); | |
prefs.put(PREF_X, x); | |
prefs.put(PREF_Y, y); | |
} | |
}); | |
// //Deadman switch checks "testing" box after 10 minutes of inactivity (no mouse, keyboard action in app) | |
// Action logout = new AbstractAction() { | |
// public void actionPerformed(ActionEvent e) { | |
// //JFrame frame = (JFrame)e.getSource(); | |
// //pop-up box to confirm still active? | |
// LOGGER.log(Level.FINEST, "Inactive Alert"); | |
// Testing.setSelected(true); | |
// //frame.dispatchEvent(new WindowEvent(frame, WindowEvent.WINDOW_CLOSING)); | |
// } | |
// }; | |
// InactivityListener listener = new InactivityListener(frame, logout, 10); | |
// listener.start(); | |
String username = System.getProperty("user.name"); | |
//LOGGER.log(Level.FINEST, "tradedate is: " + tradeDate); | |
//portfolioName //"MERGED PORTFOLIO".equals(emsx_notes) //if username is x, then portfolio is y | |
for (int i=0;i<9;i++){ | |
holidayDate[i] = GregorianCalendar.getInstance(); | |
} | |
holidayDate[0].set(2019, Calendar.JANUARY, 21); | |
holidayDate[1].set(2019, Calendar.FEBRUARY, 18); | |
holidayDate[2].set(2019, Calendar.APRIL, 19); | |
holidayDate[3].set(2019, Calendar.MAY, 27); | |
holidayDate[4].set(2019, Calendar.JULY, 4); | |
holidayDate[5].set(2019, Calendar.SEPTEMBER, 2); | |
holidayDate[6].set(2019, Calendar.NOVEMBER, 28); | |
holidayDate[7].set(2019, Calendar.DECEMBER, 25); | |
holidayDate[8].set(2020, Calendar.JANUARY, 1); | |
for (int i=0;i<9;i++){ | |
holidays.add(holidayDate[i].getTime()); | |
} | |
for (int i=0;i<3;i++){ | |
halfDayDates[i] = GregorianCalendar.getInstance(); | |
} | |
halfDayDates[0].set(2019, Calendar.JULY, 3); | |
halfDayDates[1].set(2019, Calendar.NOVEMBER, 29); | |
halfDayDates[2].set(2019, Calendar.DECEMBER, 24); | |
for (int i=0;i<3;i++){ | |
halfDays.add(halfDayDates[i].getTime()); | |
} | |
//logic to find prevBizDay here | |
for (int i=1;i<10;i++){ | |
prevBizDay = Calendar.getInstance(); | |
prevBizDay.add(Calendar.DATE, -i); | |
int dayOfWeek = prevBizDay.get(Calendar.DAY_OF_WEEK); | |
if (dayOfWeek != Calendar.SATURDAY && dayOfWeek != Calendar.SUNDAY && !holidays.contains(prevBizDay.getTime())) { | |
break; | |
} | |
} | |
myTimerDelay = initialDelayForTickers; | |
myTimer = new Timer(myTimerDelay, screenUpdate); | |
myTimer.start(); | |
} | |
public void myInitComponents() { | |
frame.remove(Load); | |
LOGGER.log(Level.FINEST, "Remove Loading Screen"); | |
panel.setLayout(new GridBagLayout()); | |
panel.setBorder(BorderFactory.createEmptyBorder(1,1,1,1)); | |
//panel.setBorder(new MatteBorder(1, 1, 1, 1, Color.GRAY)); | |
GridBagConstraints c = new GridBagConstraints(); | |
GridBagConstraints r = new GridBagConstraints(); | |
GridBagConstraints l = new GridBagConstraints(); | |
r.anchor = GridBagConstraints.EAST; | |
r.insets = new Insets(1,1,1,1); | |
l.anchor = GridBagConstraints.WEST; | |
l.insets = new Insets(1,1,1,1); | |
c.gridy = 0; | |
c.insets = new Insets(1,1,1,1); | |
//add Headers | |
for (int i=0;i<36;i++){ | |
Header[i] = new JLabel(); | |
Header[i].setBorder(new MatteBorder(0, 0, 1, 1, Color.GRAY)); | |
panel.add(Header[i],c); | |
Header[i].setForeground(Color.WHITE); | |
Header[i].setOpaque(true); | |
Header[i].setBackground(Color.BLACK); | |
} | |
Header[0].setText("SEQ"); | |
Header[1].setText("OUT"); | |
Header[2].setText("SIDE"); | |
Header[3].setText("AMOUNT"); | |
Header[4].setText("SYMBOL"); | |
Header[5].setText("TYPE"); | |
Header[6].setText("LIMIT"); | |
Header[7].setText("STAT"); | |
Header[8].setText("BRKR"); | |
Header[9].setText("STRAT"); | |
Header[10].setText("IDLE"); | |
Header[11].setText("WORK"); | |
Header[12].setText("FILLED"); | |
Header[13].setText("REM VALUE"); | |
Header[14].setText("MKT VALUE"); | |
Header[15].setText("% FILLED"); | |
Header[16].setText("%10dADV"); | |
Header[17].setText("AVG PX"); | |
Header[18].setText("ARRIVAL PX"); | |
Header[19].setText("VWAP PX"); | |
Header[20].setText("LAST"); | |
Header[21].setText("VOLUME"); | |
Header[22].setText("UPDATE"); | |
Header[23].setText("ThPx"); | |
Header[24].setText("10%OP"); | |
Header[25].setText("ALGO"); | |
Header[26].setText("A bps"); | |
Header[27].setText("V bps"); | |
Header[28].setText("Part%"); | |
Header[29].setText("Trend"); | |
Header[30].setText("BB%"); | |
Header[31].setText("RSI"); | |
Header[32].setText("Vol Chg"); | |
Header[33].setText("Spread"); | |
Header[34].setText("FavV"); | |
Header[35].setText("GroupId"); | |
c.gridy = 1; | |
r.gridy = 1; | |
l.gridy = 1; | |
for (int i=0;i<36;i++){ | |
Total[i] = new JLabel(); | |
switch (i) { | |
case 1: | |
OverRide[TradeCount] = new JCheckBox(); | |
OverRide[TradeCount].setSelected(false); | |
panel.add(OverRide[TradeCount],c); | |
break; | |
case 2: | |
Testing = new JCheckBox(); | |
Testing.setSelected(false); | |
panel.add(Testing,c); | |
break; | |
//the totals that should be right-aligned | |
case 3: | |
case 5: | |
case 7: | |
case 10: | |
case 11: | |
case 12: | |
case 14: | |
case 15: | |
case 26: | |
case 27: | |
panel.add(Total[i],r); | |
break; | |
case 4: //left-aligned | |
panel.add(Total[i],l); | |
break; | |
default: | |
panel.add(Total[i],c); | |
break; | |
} | |
Total[i].setForeground(Color.WHITE); | |
Total[i].setOpaque(true); | |
Total[i].setBackground(Color.BLACK); | |
} | |
//declare the new JLabels here, with <TradeCount> in place of the [1000] logic? | |
String value = System.getProperty("portfolio", "focus"); | |
if ("pairs".equals(value)) { | |
Collections.sort(Orders, new SortGroupId()); | |
} else { | |
//sort orders alphabetically | |
Collections.sort(Orders, new SortTickers()); | |
Collections.sort(Orders, new SortStatus()); | |
} | |
for (int i=0;i<TradeCount;i++){ | |
//center,left,right alignments | |
c.gridy = i+2; | |
c.insets = new Insets(2,2,2,2); // (top, left, bottom, right) "padding" //c.gridx = i; c.gridheight = 2; c.gridwidth = 2; | |
r.gridy = i+2; | |
r.insets = new Insets(2,2,2,2); | |
l.gridy = i+2; | |
l.insets = new Insets(2,2,2,2); | |
SEQ[i] = new JLabel(String.valueOf(Orders.get(i).sequenceNo)); | |
Symbol[i] = new JLabel(Orders.get(i).ticker); | |
VwapPx[i] = new JLabel(); | |
Side[i] = new JLabel(Orders.get(i).side); | |
Type[i] = new JLabel(Orders.get(i).type); | |
LimitPx[i] = new JLabel(px.format(Orders.get(i).limit_price)); | |
Idle[i] = new JLabel(shares.format(Orders.get(i).idle)); | |
Working[i] = new JLabel(shares.format(Orders.get(i).working)); | |
Filled[i] = new JLabel(shares.format(Orders.get(i).filled)); | |
AvgPx[i] = new JLabel((String.format("%.4f", Orders.get(i).avg_price))); | |
Amount[i] = new JLabel(shares.format(Orders.get(i).amount)); | |
Status[i] = new JLabel(String.valueOf(Orders.get(i).status)); | |
Broker[i] = new JLabel(String.valueOf(Orders.get(i).broker)); | |
Strategy[i] = new JLabel(String.valueOf(Orders.get(i).strategy)); | |
ArrivalBPS[i] = new JLabel(); | |
VwapBPS[i] = new JLabel(); | |
MarketValue[i] = new JLabel(); | |
RemValue[i] = new JLabel(); | |
ArrivalPrice[i] = new JLabel(); | |
PercentFilled[i] = new JLabel(); | |
LastAll[i] = new JLabel(); | |
LastUpdateAll[i] = new JLabel(); | |
VolumeAll[i] = new JLabel(); | |
OpenFlag[i] = new JLabel(); | |
Algo[i] = new JLabel(); | |
PercentTenDayADV[i] = new JLabel(); | |
PartRate[i] = new JLabel(); | |
ThresholdPx[i] = new JLabel(); | |
RSI[i] = new JLabel(); | |
BollPercent[i] = new JLabel(); | |
Trend[i] = new JLabel(); | |
BASpread[i] = new JLabel(); | |
FavVolume[i] = new JLabel(); | |
GroupId[i] = new JLabel(); | |
VolChg[i] = new JLabel(); | |
OverRide[i] = new JCheckBox(); | |
OverRide[i].setSelected(false); | |
SEQ[i].setForeground(Color.WHITE); | |
VwapPx[i].setForeground(Color.WHITE); | |
Symbol[i].setForeground(Color.WHITE); | |
MarketValue[i].setForeground(Color.WHITE); | |
RemValue[i].setForeground(Color.WHITE); | |
if ("SELL".equals(Orders.get(i).side) || "SHRT".equals(Orders.get(i).side)) { | |
Symbol[i].setForeground(Color.RED); | |
Side[i].setForeground(Color.RED); | |
} else { | |
Side[i].setForeground(Color.GREEN); | |
Symbol[i].setForeground(Color.GREEN); | |
} | |
Type[i].setForeground(Color.WHITE); | |
LimitPx[i].setForeground(Color.WHITE); | |
Idle[i].setForeground(Color.WHITE); | |
Working[i].setForeground(Color.WHITE); | |
Filled[i].setForeground(Color.WHITE); | |
AvgPx[i].setForeground(Color.WHITE); | |
Amount[i].setForeground(Color.WHITE); | |
Status[i].setForeground(Color.WHITE); | |
Broker[i].setForeground(Color.WHITE); | |
Strategy[i].setForeground(Color.WHITE); | |
ArrivalPrice[i].setForeground(Color.WHITE); | |
PercentFilled[i].setForeground(Color.WHITE); | |
LastAll[i].setForeground(Color.WHITE); | |
LastUpdateAll[i].setForeground(Color.WHITE); | |
VolumeAll[i].setForeground(Color.WHITE); | |
OpenFlag[i].setForeground(Color.WHITE); | |
PercentTenDayADV[i].setForeground(Color.WHITE); | |
Algo[i].setForeground(Color.WHITE); | |
ArrivalBPS[i].setForeground(Color.WHITE); | |
VwapBPS[i].setForeground(Color.WHITE); | |
PartRate[i].setForeground(Color.WHITE); | |
Trend[i].setForeground(Color.WHITE); | |
RSI[i].setForeground(Color.WHITE); | |
BollPercent[i].setForeground(Color.WHITE); | |
ThresholdPx[i].setForeground(Color.WHITE); | |
BASpread[i].setForeground(Color.WHITE); | |
FavVolume[i].setForeground(Color.WHITE); | |
GroupId[i].setForeground(Color.WHITE); | |
VolChg[i].setForeground(Color.WHITE); | |
panel.add(SEQ[i], c); | |
panel.add(OverRide[i], c); | |
panel.add(Side[i], l); | |
panel.add(Amount[i], r); | |
panel.add(Symbol[i], l); | |
panel.add(Type[i], c); | |
panel.add(LimitPx[i], r); | |
panel.add(Status[i], l); | |
panel.add(Broker[i], l); | |
panel.add(Strategy[i], l); | |
panel.add(Idle[i], r); | |
panel.add(Working[i], r); | |
panel.add(Filled[i], r); | |
panel.add(RemValue[i], r); | |
panel.add(MarketValue[i], r); | |
panel.add(PercentFilled[i], r); | |
panel.add(PercentTenDayADV[i], r); | |
panel.add(AvgPx[i], r); | |
panel.add(ArrivalPrice[i], r); | |
panel.add(VwapPx[i], l); | |
panel.add(LastAll[i], r); | |
panel.add(VolumeAll[i], r); | |
panel.add(LastUpdateAll[i], l); | |
panel.add(ThresholdPx[i], r); | |
panel.add(OpenFlag[i], c); //24th header | |
panel.add(Algo[i], l); | |
panel.add(ArrivalBPS[i], r); | |
panel.add(VwapBPS[i], r); | |
panel.add(PartRate[i], r); | |
panel.add(Trend[i], c); | |
panel.add(BollPercent[i], r); | |
panel.add(RSI[i], r); | |
panel.add(VolChg[i], r); | |
panel.add(BASpread[i], r); | |
panel.add(FavVolume[i], r); | |
panel.add(GroupId[i], r); | |
} | |
panel.setBackground(Color.BLACK); | |
GridBagConstraints b = new GridBagConstraints(); | |
b.gridx=0; | |
b.gridy=0; | |
b.gridheight = 10; //b.gridwidth = 10 | |
b.weighty = 1; | |
b.weightx = 1; | |
b.fill = GridBagConstraints.BOTH; | |
b.anchor = GridBagConstraints.NORTHWEST; | |
frame.add(panel,b); | |
JScrollPane scrollPanel = new JScrollPane(panel); | |
frame.getContentPane().add(scrollPanel, b); | |
b.gridx=0; | |
b.gridy=11; //b.weighty = 0.5; | |
b.anchor = GridBagConstraints.NORTHWEST; | |
int x2 = Integer.parseInt(prefs.get(PREF_X, "600")); | |
int y2 = Integer.parseInt(prefs.get(PREF_Y, "-800")); | |
int w2 = Integer.parseInt(prefs.get(PREF_WIDTH, "1525")); | |
int h2 = Integer.parseInt(prefs.get(PREF_HEIGHT, "700")); | |
frame.setBounds(x2, y2, w2, h2); //(x, y, width, height) //(600, -800, 800, 500); | |
panel.setVisible(true); | |
basketImbalance =0; | |
OverRide[TradeCount].setSelected(true); | |
LOGGER.log(Level.FINEST, "Initialize done"); | |
} | |
public void updateBlotter() throws ParseException { | |
cal = Calendar.getInstance(); | |
LocalDateTime now = LocalDateTime.now(); | |
IgnoreOpenMomentumIndicator ignoreOpenMomentumIndicator = new IgnoreOpenMomentumIndicator(Orders, adjPrevClose, preMktPx, sideSign); | |
for (int i=0;i<TradeCount;i++){ | |
if ((Set.of("CHF").contains(currency[i]) || ticker[i].endsWith("SW Equity")) | |
&& LocalTime.MIN.plusSeconds(Orders.get(i).time_stamp).isBefore(LocalTime.parse(officialOpenTime[i]))) { | |
Orders.get(i).arrival_price = open[i]; | |
} | |
if (LocalTime.MIN.plusSeconds(Orders.get(i).time_stamp).isBefore(LocalTime.parse(officialOpenTime[i])) | |
&& Orders.get(i).arrival_price == 0) { | |
if ((ticker[i].endsWith("US Equity") || ticker[i].endsWith("CN Equity")) | |
&& marketDataTable.row(primaryTicker[i]).containsKey(RealtimeField.PX_OFFICIAL_AUCTION_RT.toString())) { | |
Orders.get(i).arrival_price = marketDataTable.row(primaryTicker[i]).get(RealtimeField.PX_OFFICIAL_AUCTION_RT.toString()).asDouble(); | |
} else { | |
Orders.get(i).arrival_price = open[i]; | |
} | |
} | |
OrderViewModel viewModel = new OrderViewModel(Orders.get(i)); | |
Amount[i].setText(viewModel.getAmount()); | |
Idle[i].setText(viewModel.getIdle()); | |
Working[i].setText(viewModel.getWorking()); | |
Filled[i].setText(viewModel.getFilled()); | |
AvgPx[i].setText(viewModel.getAveragePrice()); | |
Status[i].setText(viewModel.getStatus()); | |
Type[i].setText(viewModel.getType()); | |
LimitPx[i].setText(viewModel.getLimitPrice()); | |
GroupId[i].setText(Orders.get(i).groupId); | |
MarketDataViewModel marketDataViewModel = new MarketDataViewModel(Orders.get(i).ticker, marketDataTable); | |
VwapPx[i].setText(String.format("%.4f", vwap[i])); | |
ArrivalPrice[i].setText(String.format("%.4f", Orders.get(i).arrival_price)); | |
PercentFilled[i].setText(perc.format(((double) Orders.get(i).filled/Orders.get(i).amount) * 100.00)); | |
PercentTenDayADV[i].setText(String.format("%.1f", Orders.get(i).amount/adv10[i] * 100.00)); | |
LastAll[i].setText(String.format("%.2f",lastAll[i])); | |
VolumeAll[i].setText(String.valueOf(shares.format(volumeAll[i]))); | |
k = 0; | |
m = 0; | |
for (int j=0;j<RouteCount;j++){ //only applicable if one order is out at a time? | |
if (Routes.get(j).sequenceNo == Orders.get(i).sequenceNo && VALID_STATUSES.contains(Routes.get(j).status)) { | |
RouteViewModel routeViewModel = new RouteViewModel(Routes.get(j)); | |
childRouteCount[i]=++k; //total child orders for the ticker | |
if (routeViewModel.isLive()){ | |
openRouteCount[i]=++m; //total open routes for the ticker | |
Strategy[i].setText(routeViewModel.getStrategy()); | |
} | |
routeStratType[j] = routeViewModel.getRouteStratType(); | |
openStratType[j] = routeViewModel.getOpenStratType(); | |
Broker[i].setText(routeViewModel.getBroker()); | |
Orders.get(i).broker = routeViewModel.getBroker(); | |
} | |
} | |
//check if market data is coming in before painting | |
if (exchange[i] != null){ | |
if (now.isBefore(closeTime[i])) { | |
sinceOpen[i] = Math.max(0, Duration.between(openTime[i], now).toMinutes()); | |
toClose[i] = Duration.between(now, closeTime[i]).toMinutes() + 1; | |
} else { | |
sinceOpen[i] = Duration.between(openTime[i], closeTime[i]).toMinutes(); | |
toClose[i] = 0; | |
} | |
if(lastUpdateAll[i] == null || "-".equals(lastUpdateAll[i].substring(4,5))){ | |
//Date update = sdf.parse(lastUpdateAll[i]); | |
//LastUpdateAll[i].setText(String.valueOf(sdf.format(update))); | |
lastUpdateAll[i] = today.format(prevBizDay.getTime()); | |
LastUpdateAll[i].setText(today.format(prevBizDay.getTime())); | |
} else { | |
Date update = sdf.parse(lastUpdateAll[i]); | |
LastUpdateAll[i].setText(String.valueOf(sdf.format(update))); | |
} | |
if (offeringPrelimFilingDate[i] != null && offeringPrelimFilingDate[i].equals(today.format(cal.getTime())) || offeringPrelimFilingDate[i].equals(today.format(prevBizDay.getTime()))) { | |
//create new variable to remove from OpenFlag logic below | |
//don't need to check this with every iteration of update blotter though | |
} | |
partRate[i] = (Orders.get(i).filled/volume[i]*100); //Orders.get(i).ticker | |
PartRate[i].setText(String.format("%.2f", (partRate[i]))); | |
if (partRate[i] > 3) { | |
PartRate[i].setForeground(Color.YELLOW); | |
} else { | |
PartRate[i].setForeground(Color.WHITE); | |
} | |
marketValue[i] = (int) ((fxRate[i])*(Orders.get(i).avg_price*Orders.get(i).filled) + (fxRate[i])*last[i]*(Orders.get(i).amount-Orders.get(i).filled)) * pxPosMultFactor[i]; | |
//LOGGER.log(Level.FINEST, "mv Test: " + marketValue[i] + "fx: " + fxRate[i] + "last: " + last[i] + "amt: " + Orders.get(i).amount + "filled: " + Orders.get(i).filled + "mult check: "+ ((fxRate[i])*(Orders.get(i).avg_price*Orders.get(i).filled) + (fxRate[i])*last[i]*(Orders.get(i).amount-Orders.get(i).filled))); | |
MarketValue[i].setText(String.valueOf(curr.format(marketValue[i]))); | |
//LOGGER.log(Level.FINEST, "FX Test: " + GrLayout.fxRate[i]); | |
remValue[i] = (int) (fxRate[i]*(Orders.get(i).amount-Orders.get(i).filled)*last[i]) * pxPosMultFactor[i]; | |
RemValue[i].setText(String.valueOf(curr.format(remValue[i]))); | |
//testing | |
//Type[i].setText(String.valueOf(divAmount[i])); | |
//graying out remvalues that are limit away | |
if ("LMT".equals(Orders.get(i).type) && LocalTime.now().isAfter(LocalTime.parse(officialOpenTime[i]))) { | |
if (TradingUtils.isLimitAway(Orders.get(i).side, Orders.get(i).limit_price, last[i]) && (Orders.get(i).working > 0 || Orders.get(i).idle > 0)) { | |
RemValue[i].setForeground(Color.GRAY); | |
MarketValue[i].setForeground(Color.GRAY); | |
FavVolume[i].setForeground(Color.GRAY); | |
limitAway[i] = "YES"; | |
} else { | |
RemValue[i].setForeground(Color.WHITE); | |
MarketValue[i].setForeground(Color.WHITE); | |
limitAway[i] = "NO"; | |
FavVolume[i].setForeground(Color.WHITE); | |
} | |
} | |
OrderTicket currentOrder = Orders.get(i); | |
boolean isLimitAway = "YES".equals(limitAway[i]); | |
boolean sellOrShort = "SELL".equals(currentOrder.side) || "SHRT".equals(currentOrder.side); | |
SlippageCalculatorBuilder slippageCalculatorBuilder = new SlippageCalculatorBuilder() | |
.setFxRate(fxRate[i]) | |
.setIsLimitAway(isLimitAway) | |
.setSellOrShort(sellOrShort) | |
.setLast(last[i]) | |
.setOrder(currentOrder); | |
SlippageCalculator slippageCalculator = slippageCalculatorBuilder.createSlippageCalculator(); | |
if (sellOrShort) { | |
sideSign[i] = 1; | |
sideLetter = "S"; | |
} else { | |
sideSign[i] = -1; | |
sideLetter = "B"; | |
} | |
arrival$[i] = slippageCalculator.getArrivalDollars(); | |
arrivalbps[i] = slippageCalculator.getArrivalSlippage(); | |
ArrivalBPS[i].setText((String.format("%.1f", arrivalbps[i] * 10000))); | |
projVwap[i] = vwap[i] * (sinceOpen[i] / fullDay[i]) + last[i] * slippageCalculator.getVwapMultiplier() * (toClose[i] / fullDay[i]); | |
vwap$[i] = sinceOpen[i] == 0 ? 0 : slippageCalculator.getVwapDollars(projVwap[i]); | |
vwapbps[i] = (float) vwap$[i] / (float) marketValue[i]; | |
VwapBPS[i].setText((String.format("%.1f", vwapbps[i] * 10000))); | |
if (arrivalbps[i] >0) { | |
ArrivalBPS[i].setForeground(Color.GREEN); | |
} else { | |
ArrivalBPS[i].setForeground(Color.RED); | |
} | |
if (vwapbps[i] >0) { | |
VwapBPS[i].setForeground(Color.GREEN); | |
} else { | |
VwapBPS[i].setForeground(Color.RED); | |
} | |
//close[i] = close[i] - divAmount[i]; | |
adjPrevClose[i] = close[i] - divAmount[i]; | |
thresholdMove[i] = Math.max((maxVol[i]/Math.sqrt(252))/100 + .01,((maxVol[i]/Math.sqrt(252))/100)*1.2); | |
thresholdPx[i] = adjPrevClose[i]*(1+sideSign[i]*thresholdMove[i]); | |
if ("US".equals(region[i])) { | |
if (broadMarketChg>0 && Math.abs(broadMarketChg) > hsd[TradeCount+1] && ("SELL".equals(Orders.get(i).side) || "SHRT".equals(Orders.get(i).side))) { | |
thresholdMove[i] = Math.max((maxVol[i]/Math.sqrt(252))/100 + .01 + (Math.abs(broadMarketChg) - hsd[TradeCount+1]),((maxVol[i]/Math.sqrt(252))/100 + (Math.abs(broadMarketChg) - hsd[TradeCount+1]))*1.2); | |
thresholdPx[i] = adjPrevClose[i]*(1+sideSign[i]*thresholdMove[i]); | |
} else if (broadMarketChg<0 && Math.abs(broadMarketChg) > hsd[TradeCount+1] && ("BUY".equals(Orders.get(i).side) || "COVR".equals(Orders.get(i).side))) { | |
thresholdMove[i] = Math.max((maxVol[i]/Math.sqrt(252))/100 + .01 + (Math.abs(broadMarketChg) - hsd[TradeCount+1]),((maxVol[i]/Math.sqrt(252))/100 + (Math.abs(broadMarketChg) - hsd[TradeCount+1]))*1.2); | |
thresholdPx[i] = adjPrevClose[i]*(1+sideSign[i]*thresholdMove[i]); | |
} else { | |
thresholdPx[i] = adjPrevClose[i]*(1+sideSign[i]*thresholdMove[i]); | |
} | |
} | |
if ((sideSign[i] == 1 && last[i] > adjPrevClose[i]*(1+hsd[i])) || (sideSign[i] == -1 && last[i] < adjPrevClose[i]*(1-hsd[i])) ){ | |
trend[i] = sideLetter + "F"; | |
} else if ((sideSign[i] == 1 && last[i] < adjPrevClose[i]*(1-hsd[i])) || (sideSign[i] == -1 && last[i] > adjPrevClose[i]*(1+hsd[i])) ){ | |
trend[i] = sideLetter + "U"; | |
} else { | |
trend[i] = "O"; | |
} | |
ThresholdPx[i].setText(String.format("%.2f",thresholdPx[i])); | |
Trend[i].setText(trend[i]); | |
BollPercent[i].setText(String.format("%.1f",bbPerc[i]*100)); | |
RSI[i].setText(String.format("%.1f",rsi[i])); | |
if ("FILLED".equals(Orders.get(i).status) || "YES".equals(limitAway[i])){ | |
BollPercent[i].setForeground(Color.GRAY); | |
RSI[i].setForeground(Color.GRAY); | |
} else if (sdf.parse(sdf.format(cal.getTime())).after(sdf.parse(afterOpen45[i])) && sdf.parse(sdf.format(cal.getTime())).before(sdf.parse(closeCutoff[i]))){ | |
BollPercent[i].setForeground(Color.WHITE); | |
RSI[i].setForeground(Color.WHITE); | |
} else { | |
BollPercent[i].setForeground(Color.GRAY); | |
RSI[i].setForeground(Color.GRAY); | |
} | |
VolChg[i].setText(perc.format(volChg1d20d[i])); | |
if (volChg1d20d[i] > 125) { | |
VolChg[i].setForeground(Color.YELLOW); | |
} else { | |
VolChg[i].setForeground(Color.WHITE); | |
} | |
bidAskSpread[i] = (ask[i]-bid[i])/last[i]*100; | |
BASpread[i].setText(String.format("%.2f",bidAskSpread[i])); // + " " + String.format("%.3f",avgBidAskSpread[i])); | |
if (bidAskSpread[i] > 0.1) { | |
BASpread[i].setForeground(Color.YELLOW); | |
} else { | |
BASpread[i].setForeground(Color.WHITE); | |
} | |
Double favorableVolumePercent = favVolume[i]/volumeAll[i]*100; | |
favVolumePerc[i] = favorableVolumePercent.isNaN() ? 0 : favorableVolumePercent; | |
FavVolume[i].setText(perc.format(favVolumePerc[i])); | |
//logic for OPEN FLAG | |
//liquidity and pre-market check | |
if (close[i] > 4 && avgvolume[i] >= 100000 && mktcap[i] >= 100000000 && sdf.parse(sdf.format(cal.getTime())).before(sdf.parse(officialOpenTime[i]))) { //add volume theo below somewhere? | |
//if favorable open indicated | |
if (priceIndicatedOpen[i] != 0 && ((sideSign[i] == 1 && priceIndicatedOpen[i] > thresholdPx[i]) || (sideSign[i] == -1 && priceIndicatedOpen[i] < thresholdPx[i])) ){ | |
openFlag[i] = "YES"; | |
OpenFlag[i].setText(openFlag[i]);OpenFlag[i].setForeground(Color.BLACK); OpenFlag[i].setOpaque(true); OpenFlag[i].setBackground(Color.YELLOW); | |
//if nyse and trading pre-market... | |
} else if (volumeAll[i]>= 500 && !"-".equals(lastUpdateAll[i].substring(4,5)) && "New York".equals(exchange[i]) && sdf.parse(lastUpdateAll[i]).after(sdf.parse("08:59:59")) && sdf.parse(lastUpdateAll[i]).before(sdf.parse("09:29:45"))){ | |
//&& !"-".equals(lastUpdateAll[i].substring(4,5)) | |
//find the appropriate pre-market price to use | |
if (sideSign[i] == -1) { | |
preMktPx[i] = Math.max(bidAll[i],Math.min(lastAll[i], askAll[i])); | |
} else { | |
preMktPx[i] = Math.min(askAll[i],Math.max(lastAll[i], bidAll[i])); | |
} | |
//if move is above/below threshold | |
if ((sideSign[i] == 1 && preMktPx[i] > thresholdPx[i]) || (sideSign[i] == -1 && preMktPx[i] < thresholdPx[i]) && !ignoreOpenMomentumIndicator.calculate(i)){ | |
openFlag[i] = "YES"; | |
OpenFlag[i].setText(openFlag[i]);OpenFlag[i].setForeground(Color.BLACK); OpenFlag[i].setOpaque(true); OpenFlag[i].setBackground(Color.YELLOW); | |
} else { | |
openFlag[i] = ""; | |
OpenFlag[i].setText(openFlag[i]);OpenFlag[i].setForeground(Color.WHITE); OpenFlag[i].setOpaque(false); OpenFlag[i].setBackground(Color.BLACK); | |
} | |
//if nasdaq and trading pre-market... | |
} else if (volumeAll[i]>= 500 && !"-".equals(lastUpdateAll[i].substring(4,5)) && "NASDAQ".equals(exchange[i].substring(0,6)) && sdf.parse(lastUpdateAll[i]).after(sdf.parse("08:59:59")) && sdf.parse(lastUpdateAll[i]).before(sdf.parse("09:27:45"))){ | |
//&& !"-".equals(lastUpdateAll[i].substring(4,5)) | |
//find the appropriate pre-market price to use | |
if (sideSign[i] == -1) { | |
preMktPx[i] = Math.max(bidAll[i],Math.min(lastAll[i], askAll[i])); | |
} else { | |
preMktPx[i] = Math.min(askAll[i],Math.max(lastAll[i], bidAll[i])); | |
} | |
//if move is above/below threshold | |
if ((sideSign[i] == 1 && preMktPx[i] > thresholdPx[i]) || (sideSign[i] == -1 && preMktPx[i] < thresholdPx[i]) && !ignoreOpenMomentumIndicator.calculate(i)){ | |
openFlag[i] = "YES"; | |
OpenFlag[i].setText(openFlag[i]);OpenFlag[i].setForeground(Color.BLACK); OpenFlag[i].setOpaque(true); OpenFlag[i].setBackground(Color.YELLOW); | |
} else { | |
openFlag[i] = ""; | |
OpenFlag[i].setText(openFlag[i]);OpenFlag[i].setForeground(Color.WHITE); OpenFlag[i].setOpaque(false); OpenFlag[i].setBackground(Color.BLACK); | |
} | |
} else { | |
openFlag[i] = ""; | |
OpenFlag[i].setText(openFlag[i]);OpenFlag[i].setForeground(Color.WHITE); OpenFlag[i].setOpaque(false); OpenFlag[i].setBackground(Color.BLACK); | |
} | |
}//end of pre open check | |
} //end lastupdatedate null check | |
} //end traddecount loop | |
//updating the aggregated values in row 2 | |
Total[0].setText(String.valueOf(TradeCount)); | |
Total[4].setText("SPY US Equity"); | |
broadMarketChg = (lastAll[TradeCount+1]/close[TradeCount+1]-1); | |
Total[5].setText(chg.format(broadMarketChg*100)); | |
if (broadMarketChg>0) { | |
Total[4].setForeground(Color.GREEN); | |
Total[5].setForeground(Color.GREEN); | |
} else { | |
Total[4].setForeground(Color.RED); | |
Total[5].setForeground(Color.RED); | |
} | |
Total[7].setText("SXXPIEX GY"); | |
EUbroadMarketChg = (last[TradeCount+2]/close[TradeCount+2]-1)*100; | |
Total[8].setText(chg.format(EUbroadMarketChg)); | |
if (EUbroadMarketChg>0) { | |
Total[7].setForeground(Color.GREEN); | |
Total[8].setForeground(Color.GREEN); | |
} else { | |
Total[7].setForeground(Color.RED); | |
Total[8].setForeground(Color.RED); | |
} | |
remSell = 0; remBuy = 0; | |
OpenCount = 0; | |
amountTotal = 0; | |
idleTotal = 0; | |
workingTotal = 0; | |
filledTotal = 0; | |
for (int i=0;i<TradeCount;i++){ | |
amountTotal += Orders.get(i).amount; | |
idleTotal += Orders.get(i).idle; | |
workingTotal += Orders.get(i).working; | |
filledTotal += Orders.get(i).filled; | |
if("YES".equals(openFlag[i])){ | |
++OpenCount; | |
} | |
if(("SELL".equals(Orders.get(i).side) || "SHRT".equals(Orders.get(i).side)) && (last[i]>Orders.get(i).limit_price || ("MKT".equals(Orders.get(i).type) && Orders.get(i).filled < Orders.get(i).amount))){ | |
remSell += remValue[i]; | |
} else if (("BUY".equals(Orders.get(i).side) || "COVR".equals(Orders.get(i).side)) && (last[i]<Orders.get(i).limit_price || ("MKT".equals(Orders.get(i).type) && Orders.get(i).filled < Orders.get(i).amount))){ | |
remBuy += remValue[i]; | |
} | |
} | |
Total[3].setText(shares.format(amountTotal)); //fix | |
Total[10].setText(shares.format(idleTotal)); | |
Total[11].setText(shares.format(workingTotal)); | |
Total[12].setText(shares.format(filledTotal)); | |
Total[13].setText(curr.format(remBuy+remSell)); | |
if (OpenCount>0){ | |
Total[24].setText(String.valueOf(OpenCount)); | |
Total[24].setForeground(Color.BLACK);Total[24].setOpaque(true);Total[24].setBackground(Color.YELLOW); | |
} else { | |
Total[24].setText(""); | |
Total[24].setForeground(Color.WHITE);Total[24].setBackground(Color.BLACK); | |
} | |
imbalance = remBuy - remSell; | |
if (imbalance>0 && basketImbalance==1) { | |
Total[25].setForeground(Color.GREEN); | |
} else if (imbalance<0 && basketImbalance==1){ | |
Total[25].setForeground(Color.RED); | |
} else { | |
Total[25].setForeground(Color.WHITE); | |
} | |
Total[25].setText(curr.format(imbalance)); //curr.format(remSell) + " " + curr.format(remBuy) + | |
if (IntStream.of(marketValue).sum() > 0) { | |
totalArrival$ = 0; | |
totalVwap$ = 0; | |
totalMV = 0; | |
for (int i = 0; i < TradeCount; i++) { | |
if (!TradingUtils.isLimitAway(Orders.get(i).side, Orders.get(i).limit_price, last[i])) { | |
totalArrival$ += arrival$[i]; | |
totalVwap$ += vwap$[i]; | |
totalMV += marketValue[i]; | |
} else { | |
double percentFilled = ((double)Orders.get(i).filled/Orders.get(i).amount); | |
totalArrival$ += arrival$[i] * percentFilled; | |
totalVwap$ += vwap$[i] * percentFilled; | |
totalMV += marketValue[i] * percentFilled; | |
} | |
} | |
totalArrivalBps = totalArrival$ / totalMV * 10000; | |
totalVwapBps = totalVwap$ / totalMV * 10000; | |
} | |
Total[14].setText(curr.format(totalMV)); | |
Total[26].setText(String.format("%.1f", totalArrivalBps)); | |
Total[27].setText(String.format("%.1f", totalVwapBps)); | |
if (totalArrivalBps>0) { | |
Total[26].setForeground(Color.GREEN); | |
} else { | |
Total[26].setForeground(Color.RED); | |
} | |
if (totalVwapBps>0) { | |
Total[27].setForeground(Color.GREEN); | |
} else { | |
Total[27].setForeground(Color.RED); | |
} | |
} | |
private static final Set<String> LOGS = new HashSet<>(); | |
public void pairsTradeLogic() { | |
populateOpeningTrades(); | |
checkIfOverrideIsSelected(); | |
// TICKER_TO_PRIMARY_TICKER.entrySet().stream().map((Map.Entry<String, String> entry) -> { | |
// int openVolume = marketDataTable.row(entry.getValue()).containsKey(Fields.OPENING_VOLUME_AVG) ? marketDataTable.row(entry.getValue()).get(Fields.OPENING_VOLUME_AVG).asInt() : 0; | |
// System.out.println(entry.getKey() + " " + openVolume); | |
// List<SubmitOrderRequest> initialOnOpenOrders = openAuctionTransactionManager.getIntialOnOpenOrders(entry.getKey(), openVolume, maxPctOfOpen, competingPercentOfOpen); | |
// return List.of(); | |
// }); | |
LocalTime referenceTime = LocalTime.now(); | |
ScheduleManager scheduleManager = new ScheduleManager(LocalTime.now()); | |
Map<String, Double> groupIdOrderPct = new HashMap<>(); | |
Map<String, Boolean> groupIdCannotClearOpen = new HashMap<>(); | |
Map<Integer, SubmitOrderRequest> sequenceToOrder = new HashMap<>(sequenceToSubmitOrderRequest); // make a copy | |
Map<Integer, Integer> chunkSizes = new HashMap<>(); | |
int chunks = 20; | |
// Rules | |
// 1. If both can fill open, send all to open. | |
// 2. If either cannot fill open, sending the proportional amounts to the open. | |
// 3. Amount remaining after the open should be balanced. | |
// 4. Handle multi-region | |
for (int i = 0; i < TradeCount; i++) { | |
SubmitOrderRequest submitOrderRequest = new SubmitOrderRequest(sequenceToOrder.get(Orders.get(i).sequenceNo)); | |
double amount = Orders.get(i).amount; | |
double openPctOfOrder = Precision.round(submitOrderRequest.getAmount() / amount, 2); | |
if (openPctOfOrder < groupIdOrderPct.getOrDefault(Orders.get(i).groupId, Double.MAX_VALUE)) { | |
groupIdOrderPct.put(Orders.get(i).groupId, openPctOfOrder); | |
} | |
} | |
for (int i = 0; i < TradeCount; i++) { | |
/* if ("FILLED".equals(Orders.get(i).status) || LocalTime.now().isAfter(closeTime[i].toLocalTime())) { | |
Algo[i].setForeground(Color.GRAY); | |
Algo[i].setBackground(Color.BLACK); | |
Algo[i].setText("OUT"); | |
} else */ if (scheduleManager.isBefore(officialOpenTime[i]) || true) { | |
if (TradingUtils.shouldBeRoutedToTheOpen(Orders.get(i).status, referenceTime, officialOpenTime[i], Orders.get(i).broker) || true) { | |
SubmitOrderRequest submitOrderRequest = sequenceToSubmitOrderRequest.get(Orders.get(i).sequenceNo); | |
openAuctionTransactionManager.updateBrokerPreferences(submitOrderRequest, Orders.get(i).amount, region[i], close[i], roundFactor[i], sideSign[i], 0.45, PortfolioName.FOCUS); | |
double amount = Orders.get(i).amount; | |
double openPctOfOrder = Precision.round(submitOrderRequest.getAmount() / amount, 2); | |
double maxOpenPctOfOrder = groupIdOrderPct.get(Orders.get(i).groupId); | |
if (openPctOfOrder > maxOpenPctOfOrder) { | |
submitOrderRequest.setAmount((int)(amount * maxOpenPctOfOrder)); | |
} | |
if (Testing.isSelected() || OverRide[i].isSelected() && isOverrideSelected(i)) { | |
if (!LOGS.contains(submitOrderRequest.toString())) { | |
LOGGER.log(Level.FINEST, submitOrderRequest.toString()); | |
LOGS.add(submitOrderRequest.toString()); | |
} | |
} else { | |
transactionManager.addOrder(submitOrderRequest); | |
Orders.get(i).status = "WORKING"; | |
} | |
Algo[i].setText(submitOrderRequest.getDescription()); | |
Algo[i].setForeground(Color.WHITE); | |
Algo[i].setBackground(Color.BLACK); | |
} | |
} else { | |
} | |
} | |
} | |
private Map<String, List<OrderTicket>> groupByGroupId(List<OrderTicket> orderList) { | |
Map<String, List<OrderTicket>> groupedObjects = new HashMap<>(); | |
for (OrderTicket objectData : orderList) { | |
String groupIdentifier = objectData.groupId; | |
if (!groupedObjects.containsKey(groupIdentifier)) { | |
groupedObjects.put(groupIdentifier, new ArrayList<>()); | |
} | |
groupedObjects.get(groupIdentifier).add(objectData); | |
} | |
return groupedObjects; | |
} | |
public void pairsTradeLogic2() { | |
Map<String, List<OrderTicket>> groupedOrders = groupByGroupId(Orders); | |
Map<String, Integer> groupMaxOpenAmounts = new HashMap<>(); | |
Map<String, Double> tickerToCurrencyAdjPx = new HashMap<>(); | |
for (Map.Entry<String, List<OrderTicket>> entry : groupedOrders.entrySet()) { | |
System.out.println("Group ID: " + entry.getKey()); | |
double groupMaxDollarAmount = Double.MAX_VALUE; | |
for (OrderTicket objectData : entry.getValue()) { | |
double maxPctOfOpen = TradingUtils.isFuturesExpiration(LocalDate.now()) ? 0.25 : 0.20; | |
int openVolume = marketDataTable.row(TICKER_TO_PRIMARY_TICKER.get(objectData.ticker)).get(Fields.OPENING_VOLUME_AVG).asInt(); | |
double currencyAdjPx = marketDataTable.row(objectData.ticker).get("CRNCY_ADJ_PX_LAST").asDouble(); | |
tickerToCurrencyAdjPx.put(objectData.ticker, currencyAdjPx); | |
int maxOpenVolume = (int) Math.min(objectData.amount, openVolume * maxPctOfOpen); | |
double maxDollarAmount = maxOpenVolume * currencyAdjPx; | |
if (maxDollarAmount < groupMaxDollarAmount) { | |
groupMaxDollarAmount = maxDollarAmount; | |
} | |
} | |
groupMaxOpenAmounts.put(entry.getKey(), (int)groupMaxDollarAmount); | |
System.out.println(); | |
} | |
System.out.println(groupMaxOpenAmounts); | |
for (Map.Entry<String, List<OrderTicket>> entry : groupedOrders.entrySet()) { | |
System.out.println("Group ID: " + entry.getKey()); | |
int maxAmount = groupMaxOpenAmounts.get(entry.getKey()); | |
List<SubmitOrderRequest> intialOnOpenOrders = openAuctionTransactionManager.getIntialOnOpenOrders(entry.getValue(), tickerToCurrencyAdjPx, maxAmount); | |
System.out.println(intialOnOpenOrders); | |
System.out.println(); | |
} | |
} | |
private static final ArrayBlockingQueue<SubmitOrderRequest> submitOrderQueue = new ArrayBlockingQueue<>(1000); | |
private static final Map<Integer, SubmitOrderRequest> sequenceToSubmitOrderRequest = new HashMap<>(); | |
private static final SecurityTransactionManager transactionManager = new SecurityTransactionManager(Orders, Routes); | |
private static final OpenAuctionTransactionManager openAuctionTransactionManager = new OpenAuctionTransactionManager(Orders, Routes); | |
private static final List<SubmitOrderRequest> onOpenOrderRequests = new ArrayList<>(); | |
private static final String[] routeType = new String[1000]; | |
public static void populateOpeningTrades() { | |
double maxPctOfOpen = TradingUtils.isFuturesExpiration(LocalDate.now()) ? 0.25 : 0.20; | |
if (sequenceToSubmitOrderRequest.isEmpty()) { | |
TICKER_TO_PRIMARY_TICKER.entrySet().stream().map((Map.Entry<String, String> entry) -> { | |
double competingPercentOfOpen = WSTI_ORDER_OBSERVER.getCompetingOpenPercent(entry.getValue(), entry.getKey(), TimeFrame.HISTORICAL); | |
int openVolume = marketDataTable.row(entry.getValue()).containsKey(Fields.OPENING_VOLUME_AVG) ? marketDataTable.row(entry.getValue()).get(Fields.OPENING_VOLUME_AVG).asInt() : 0; | |
List<SubmitOrderRequest> initialOnOpenOrders = openAuctionTransactionManager.getIntialOnOpenOrders(entry.getKey(), openVolume, maxPctOfOpen, competingPercentOfOpen); | |
return initialOnOpenOrders; | |
}).map(initialOnOpenOrders -> { | |
submitOrderQueue.addAll(initialOnOpenOrders); | |
return initialOnOpenOrders; | |
}).forEachOrdered(initialOnOpenOrders -> { | |
onOpenOrderRequests.addAll(initialOnOpenOrders); | |
}); | |
for (SubmitOrderRequest submitOrderRequest : onOpenOrderRequests) { | |
sequenceToSubmitOrderRequest.put(submitOrderRequest.getSequence(), submitOrderRequest); | |
} | |
} | |
} | |
public void dsTradeLogic() { | |
checkIfOverrideIsSelected(); | |
LocalTime referenceTime = LocalTime.now(); | |
ScheduleManager scheduleManager = new ScheduleManager(referenceTime); | |
for (int i = 0; i < TradeCount; i++) { | |
OrderTicket currentOrder = Orders.get(i); | |
boolean isLimitAway = "YES".equals(limitAway[i]); | |
boolean sellOrShort = "SELL".equals(currentOrder.side) || "SHRT".equals(currentOrder.side); | |
if ("FILLED".equals(Orders.get(i).status) || referenceTime.isAfter(closeTime[i].toLocalTime())) { | |
Algo[i].setForeground(Color.GRAY); | |
Algo[i].setBackground(Color.BLACK); | |
Algo[i].setText("OUT"); | |
} else if (scheduleManager.isBefore(officialOpenTime[i])) { | |
if (TradingUtils.shouldBeRoutedToTheOpen(Orders.get(i).status, referenceTime, officialOpenTime[i], Orders.get(i).broker)) { | |
int openVolume = marketDataTable.row(currentOrder.ticker) | |
.containsKey(Fields.OPENING_VOLUME_AVG) ? marketDataTable.row(TICKER_TO_PRIMARY_TICKER.get(currentOrder.ticker)).get(Fields.OPENING_VOLUME_AVG).asInt() : 0; | |
int competingNumberOfTrades = OrderSizing.getNumberOfCompetingTrades(currentOrder, Orders); | |
double povBasedOnCompeting = OrderSizing.getPovBasedOnNumberOfCompetingTrades(competingNumberOfTrades); | |
int maxAmountSentToOpen = (int) (povBasedOnCompeting * openVolume); | |
int targetAmount = OrderSizing.getOrderSizeFromMaxAmount(maxAmountSentToOpen, currentOrder.amount); | |
// TODO: Amount should be correct number of shares for US case | |
SubmitOrderRequest submitOrderRequest = new SubmitOrderRequest( | |
currentOrder.sequenceNo, | |
targetAmount, | |
OrderType.getEnum(currentOrder.type), | |
StrategyType.DMA, | |
currentOrder.ticker, | |
currentOrder.limit_price, | |
currentOrder.broker | |
); | |
submitOrderRequest.setPov(OrderSizing.getPovBasedOnNumberOfCompetingTrades(competingNumberOfTrades)); | |
int sellOrShortValue = sellOrShort ? 1 : -1; | |
openAuctionTransactionManager.updateBrokerPreferences(submitOrderRequest, Orders.get(i).amount, region[i], close[i], roundFactor[i], sellOrShortValue, 0.45, PortfolioName.A_PLUS); | |
if (Testing.isSelected() || OverRide[i].isSelected() && isOverrideSelected(i)) { | |
if (!LOGS.contains(submitOrderRequest.toString())) { | |
LOGGER.log(Level.FINEST, submitOrderRequest.toString()); | |
LOGS.add(submitOrderRequest.toString()); | |
} | |
} else { | |
transactionManager.addOrder(submitOrderRequest); | |
Orders.get(i).status = "WORKING"; | |
} | |
Algo[i].setText(submitOrderRequest.getDescription()); | |
Algo[i].setForeground(Color.WHITE); | |
Algo[i].setBackground(Color.BLACK); | |
} | |
} else if (isAfterOpen(scheduleManager, i)) { | |
routeOrderToLSA(i); | |
} else if (isAfterOpenPlusTen(scheduleManager, i) | |
|| TradingUtils.isLimitAway(Orders.get(i).side, Orders.get(i).limit_price, last[i])) { | |
routeOrderToLimit(i); | |
} else if (scheduleManager.isAfter(closeCutoff[i])) { | |
routeOrderToVWAP(i); | |
} | |
} | |
} | |
public void aplusTradeLogic() throws Exception { | |
populateOpeningTrades(); | |
checkIfOverrideIsSelected(); | |
LocalTime referenceTime = LocalTime.now(); | |
// LocalTime referenceTime = LocalTime.parse("09:00:00"); | |
ScheduleManager scheduleManager = new ScheduleManager(referenceTime); | |
OrderTracker tracker = new OrderTracker(); | |
for (int i = 0; i < TradeCount; i++) { | |
tracker.addOrder(Orders.get(i).ticker, Orders.get(i).side, Orders.get(i).status); | |
} | |
for (int i = 0; i < TradeCount; i++) { | |
OrderTicket currentOrder = Orders.get(i); | |
boolean isLimitAway = "YES".equals(limitAway[i]); | |
boolean sellOrShort = "SELL".equals(currentOrder.side) || "SHRT".equals(currentOrder.side); | |
SlippageCalculatorBuilder slippageCalculatorBuilder = new SlippageCalculatorBuilder() | |
.setFxRate(fxRate[i]) | |
.setIsLimitAway(isLimitAway) | |
.setSellOrShort(sellOrShort) | |
.setLast(last[i]) | |
.setOrder(currentOrder); | |
SlippageCalculator slippageCalculator = slippageCalculatorBuilder.createSlippageCalculator(); | |
// double arrivalSlippage = slippageCalculator.getArrivalSlippage() * 10_000; | |
if ("FILLED".equals(Orders.get(i).status) || referenceTime.isAfter(closeTime[i].toLocalTime())) { | |
Algo[i].setForeground(Color.GRAY); | |
Algo[i].setBackground(Color.BLACK); | |
Algo[i].setText("OUT"); | |
} else if (scheduleManager.isBefore(officialOpenTime[i])) { | |
if (TradingUtils.shouldBeRoutedToTheOpen(Orders.get(i).status, referenceTime, officialOpenTime[i], Orders.get(i).broker)) { | |
SubmitOrderRequest submitOrderRequest = sequenceToSubmitOrderRequest.get(Orders.get(i).sequenceNo); | |
if (submitOrderRequest != null) { | |
int sellOrShortValue = sellOrShort ? 1 : -1; | |
openAuctionTransactionManager.updateBrokerPreferences(submitOrderRequest, Orders.get(i).amount, region[i], close[i], roundFactor[i], sellOrShortValue, 0.45, PortfolioName.A_PLUS); | |
if (Testing.isSelected() || OverRide[i].isSelected() && isOverrideSelected(i)) { | |
if (!LOGS.contains(submitOrderRequest.toString())) { | |
LOGGER.log(Level.FINEST, submitOrderRequest.toString()); | |
LOGS.add(submitOrderRequest.toString()); | |
} | |
} else { | |
transactionManager.addOrder(submitOrderRequest); | |
Orders.get(i).status = "WORKING"; | |
} | |
Algo[i].setText(submitOrderRequest.getDescription()); | |
Algo[i].setForeground(Color.WHITE); | |
Algo[i].setBackground(Color.BLACK); | |
} else { | |
Algo[i].setText("WAITING"); | |
Algo[i].setForeground(Color.WHITE); | |
Algo[i].setBackground(Color.BLACK); | |
} | |
} | |
} else if (tracker.hasPendingClosingOrder(Orders.get(i).ticker, Orders.get(i).side)) { | |
LOGGER.log(Level.FINEST, String.format("%s %s is a competing order/waiting to route...", Orders.get(i).ticker, Orders.get(i).side)); | |
Algo[i].setText("WAITING"); | |
Algo[i].setForeground(Color.WHITE); | |
Algo[i].setBackground(Color.BLACK); | |
} else if (isAfterOpen(scheduleManager, i)) { | |
routeOrderToLSA(i); | |
} else if (isAfterOpenPlusTen(scheduleManager, i) | |
|| TradingUtils.isLimitAway(Orders.get(i).side, Orders.get(i).limit_price, last[i])) { | |
routeOrderToLimit(i); | |
} else if (scheduleManager.isAfter(closeCutoff[i])) { | |
routeOrderToVWAP(i); | |
} | |
} // end for | |
} | |
private void routeOrderToVWAP(int i) { | |
if ("VWAP".equals(routeType[i]) && newLimitPx[i] == Orders.get(i).limit_price || Testing.isSelected() || isOverrideOnlySelected(i)) { | |
Algo[i].setText("VWAP " + Orders.get(i).limit_price); | |
Algo[i].setForeground(Color.WHITE); | |
Algo[i].setBackground(Color.BLACK); | |
} else { | |
transactionManager.addOrUpdateOrder( | |
Orders.get(i).sequenceNo, | |
Orders.get(i).idle, | |
OrderType.getEnum(Orders.get(i).type), | |
StrategyType.VWAP, | |
ticker[i], | |
Orders.get(i).limit_price, | |
Orders.get(i).broker | |
); | |
routeType[i] = "VWAP"; | |
newLimitPx[i] = Orders.get(i).limit_price; | |
} | |
} | |
private void routeOrderToLimit(int i) { | |
if (("LSA".equals(routeType[i]) && newLimitPx[i] == Orders.get(i).limit_price) || Testing.isSelected() || isOverrideOnlySelected(i)) { | |
Algo[i].setText("LSA1 " + Orders.get(i).limit_price); | |
Algo[i].setForeground(Color.WHITE); | |
Algo[i].setBackground(Color.BLACK); | |
} else { | |
transactionManager.cancelOrder(Orders.get(i).sequenceNo); | |
transactionManager.waitTillIdle(Orders.get(i)); | |
transactionManager.addOrUpdateOrder( | |
Orders.get(i).sequenceNo, | |
Orders.get(i).idle, | |
OrderType.getEnum(Orders.get(i).type), | |
StrategyType.LSA1, | |
ticker[i], | |
Orders.get(i).limit_price, | |
Orders.get(i).broker | |
); | |
routeType[i] = "LSA"; | |
newLimitPx[i] = Orders.get(i).limit_price; | |
} | |
} | |
private void routeOrderToLSA(int i) { | |
LimitPriceCalculator arrivalLimitPriceCalculator = new LimitPriceCalculatorBuilder() | |
.setPrice(Orders.get(i).arrival_price) | |
.setLimit(Orders.get(i).limit_price) | |
.setRoundFactor(roundFactor[i]) | |
.setBps(SLIPPAGE_BPS) | |
.setSide(TradeSideType.from(Orders.get(i).side)) | |
.setType(ARRIVAL) | |
.build(); | |
double newLimitPrice = arrivalLimitPriceCalculator.calculate(AlgorithmType.LSA1); | |
if ("LSA".equals(routeType[i]) && newLimitPx[i] == newLimitPrice || Testing.isSelected() || isOverrideOnlySelected(i)) { | |
Algo[i].setText("LSA1 " + newLimitPrice); | |
Algo[i].setForeground(Color.WHITE); | |
Algo[i].setBackground(Color.BLACK); | |
} else { | |
if (BrokerCode.JEFA.equals(Orders.get(i).broker)) { | |
transactionManager.cancelOrder(Orders.get(i).sequenceNo); | |
transactionManager.waitTillIdle(Orders.get(i)); | |
} | |
transactionManager.addOrUpdateOrder( | |
Orders.get(i).sequenceNo, | |
Orders.get(i).idle, | |
OrderType.getEnum(Orders.get(i).type), | |
StrategyType.LSA1, | |
ticker[i], | |
newLimitPrice, | |
Orders.get(i).broker | |
); | |
routeType[i] = "LSA"; | |
newLimitPx[i] = newLimitPrice; | |
} | |
} | |
private boolean isAfterOpenPlusTen(ScheduleManager scheduleManager, int i) { | |
return scheduleManager.isAfter(officialOpenTime[i]) | |
&& scheduleManager.isAfter(openTimePlus10[i]) | |
&& scheduleManager.isBefore(closeCutoff[i]); | |
} | |
private boolean isAfterOpen(ScheduleManager scheduleManager, int i) { | |
return scheduleManager.isAfter(officialOpenTime[i]) // TODO: Fix issue where routed one minute before open | |
&& scheduleManager.isBefore(openTimePlus10[i]) | |
&& Orders.get(i).arrival_price != 0 | |
&& Orders.get(i).filled > 0; | |
} | |
public void tradeLogic() throws ParseException, Exception{ | |
cal = Calendar.getInstance(); | |
checkIfOverrideIsSelected(); | |
for (int i=0;i<TradeCount;i++){ //go through each focus security for trade checks | |
LimitPriceCalculator lastBasedCalculator = new LimitPriceCalculatorBuilder() | |
.setPrice(last[i]) | |
.setLimit(Orders.get(i).limit_price) | |
.setRoundFactor(roundFactor[i]) | |
.setBps(SLIPPAGE_BPS) | |
.setSide(TradeSideType.from(Orders.get(i).side)) | |
.setType(LAST) | |
.build(); | |
//check if order is override, filled, not ready... | |
if (isOverrideSelected(i)) { | |
setOverrideSelected(i); | |
} else if (Orders.get(i).filled > 0 && Orders.get(i).working == 0 && Orders.get(i).idle > 0 && "YES".equals(openFlag[i])){ //remaining open flag trades | |
LOGGER.log(Level.FINEST, "Open Idle Trade @" + sdf.format(cal.getTime())); | |
limitString[i] = "EMSX_LIMIT_PRICE=" + (double) Math.round((Orders.get(i).arrival_price * (1+(sideSign[i]*0.001)))*roundFactor[i])/roundFactor[i]; | |
newLimitPx[i] = (double) Math.round((Orders.get(i).arrival_price * (1+(sideSign[i]*0.001)))*roundFactor[i])/roundFactor[i]; | |
Algo[i].setText("LSA1O " + newLimitPx[i]); | |
algoInput = new String[]{"EMSX_SEQUENCE=" + String.valueOf(Orders.get(i).sequenceNo), | |
"EMSX_AMOUNT=" + String.valueOf(Orders.get(i).idle), | |
"EMSX_ORDER_TYPE=LMT", | |
"EMSX_TIF=DAY","EMSX_HAND_INSTRUCTION=ANY", | |
"EMSX_TICKER=" + ticker[i], | |
limitString[i], | |
"EMSX_BROKER=" + Orders.get(i).broker, | |
"ALGO_TYPE=LSA1"}; | |
RouteAlgo routeAlgo = new RouteAlgo(); | |
if (Orders.get(i).idle > Orders.get(i).amount || Testing.isSelected() || ((sideSign[i] == -1 && newLimitPx[i] > Orders.get(i).limit_price) || (sideSign[i] == 1 && newLimitPx[i] < Orders.get(i).limit_price))){ | |
LOGGER.log(Level.FINEST, "REJECT/TESTING"); | |
} else { | |
routeAlgo.run(algoInput); | |
} | |
//when book becomes balanced after an imbalance and multiple routes were cancelled back | |
} else if (Orders.get(i).filled > 0 && Orders.get(i).working == 0 && Orders.get(i).idle > 0 && (basketImbalance==0)) { | |
LOGGER.log(Level.FINEST, "Balanced Idle Trade @" + sdf.format(cal.getTime())); | |
if ("MKT".equals(Orders.get(i).type)) { | |
limitString[i] = "EMSX_LIMIT_PRICE=-99999"; | |
} else { | |
limitString[i] = "EMSX_LIMIT_PRICE=" + String.valueOf(Orders.get(i).limit_price); | |
} | |
algoInput = new String[]{"EMSX_SEQUENCE=" + String.valueOf(Orders.get(i).sequenceNo), | |
"EMSX_AMOUNT=" + String.valueOf(Orders.get(i).idle), | |
"EMSX_ORDER_TYPE=" + Orders.get(i).type,"EMSX_TIF=DAY","EMSX_HAND_INSTRUCTION=ANY", | |
"EMSX_TICKER=" + ticker[i], | |
limitString[i], | |
"EMSX_BROKER=" + Orders.get(i).broker, | |
"ALGO_TYPE=VWAP"}; | |
RouteAlgo routeAlgo = new RouteAlgo(); | |
if (Orders.get(i).idle > Orders.get(i).amount || Testing.isSelected()){ | |
LOGGER.log(Level.FINEST, "REJECT/TESTING"); | |
} else { | |
routeAlgo.run(algoInput); | |
Orders.get(i).idle = 0; | |
} | |
} else if (basketImbalance==1 && Orders.get(i).idle > 0 ){ //imbalance idle trades //need to adjust for when it flips to 0 | |
LOGGER.log(Level.FINEST, "Imbalance Idle Trade @" + sdf.format(cal.getTime())); | |
imbalanceAdjust[i] = "YES"; | |
newLimitPx[i] = lastBasedCalculator.calculate(AlgorithmType.LSA1); | |
limitString[i] = "EMSX_LIMIT_PRICE=" + String.valueOf(newLimitPx[i]); | |
algoInput = new String[]{"EMSX_SEQUENCE=" + String.valueOf(Orders.get(i).sequenceNo), | |
"EMSX_AMOUNT=" + String.valueOf(Orders.get(i).idle), | |
"EMSX_ORDER_TYPE=LMT","EMSX_TIF=DAY","EMSX_HAND_INSTRUCTION=ANY", | |
"EMSX_TICKER=" + ticker[i], | |
limitString[i], | |
"EMSX_BROKER=" + Orders.get(i).broker, | |
"ALGO_TYPE=LSA1"}; | |
RouteAlgo routeAlgo = new RouteAlgo(); | |
if (Orders.get(i).idle > Orders.get(i).amount || Testing.isSelected()){ | |
LOGGER.log(Level.FINEST, "REJECT/TESTING"); | |
} else { | |
routeAlgo.run(algoInput); | |
Orders.get(i).idle = 0; | |
} | |
} else if (("ASSIGN".equals(Orders.get(i).status) || "NEW".equals(Orders.get(i).status)) && sdf.parse(sdf.format(cal.getTime())).after(sdf.parse(officialOpenTime[i])) ){ //orders that got cancelled and are limit away | |
LOGGER.log(Level.FINEST, "Limit Away Idle Trade @" + sdf.format(cal.getTime())); | |
if ("MKT".equals(Orders.get(i).type)) { | |
limitString[i] = "EMSX_LIMIT_PRICE=-99999"; | |
} else { | |
newLimitPx[i] = Orders.get(i).limit_price; | |
limitString[i] = "EMSX_LIMIT_PRICE=" + String.valueOf(newLimitPx[i]); | |
} | |
Algo[i].setText("VWAPa " + newLimitPx[i]); | |
algoInput = new String[]{"EMSX_SEQUENCE=" + String.valueOf(Orders.get(i).sequenceNo), | |
"EMSX_AMOUNT=" + String.valueOf(Orders.get(i).idle), | |
"EMSX_ORDER_TYPE=" + Orders.get(i).type,"EMSX_TIF=DAY","EMSX_HAND_INSTRUCTION=ANY", | |
"EMSX_TICKER=" + ticker[i], | |
limitString[i], | |
"EMSX_BROKER=" + Orders.get(i).broker, | |
"ALGO_TYPE=VWAP"}; | |
RouteAlgo routeAlgo = new RouteAlgo(); | |
if (Orders.get(i).idle > Orders.get(i).amount || Testing.isSelected()){ | |
LOGGER.log(Level.FINEST, "REJECT/TESTING"); | |
} else { | |
routeAlgo.run(algoInput); | |
} | |
} else if (isNotRoutedAndShouldBeRouted(i)) { | |
routeOrderToOpen(i, null, ExecutionModelType.FOCUS); | |
} | |
else { //not "OUT" and no idle amount | |
for (int j = 0; j < RouteCount; j++) {//run through each active route for each approved broker for modify trade logic | |
if (Routes.get(j).sequenceNo == Orders.get(i).sequenceNo && ("WORKING".equals(Routes.get(j).status) || "PARTFILL".equals(Routes.get(j).status))) { | |
//openSignal trade | |
if ("YES".equals(openFlag[i]) && (("NASDAQ".equals(exchange[i].substring(0,6)) && sdf.parse(sdf.format(cal.getTime())).after(sdf.parse("09:27:30")) && sdf.parse(sdf.format(cal.getTime())).before(sdf.parse(officialOpenTime[i]))) | |
|| ("New York".equals(exchange[i]) && sdf.parse(sdf.format(cal.getTime())).after(sdf.parse("09:29:30")) && sdf.parse(sdf.format(cal.getTime())).before(sdf.parse(officialOpenTime[i]))))) { | |
algo[j] = routeStratType[j]; | |
Algo[i].setText(algo[j] + " OpenFlag"); | |
if (Routes.get(j).amount != (int) Math.ceil(.10* Orders.get(i).amount)) { | |
LOGGER.log(Level.FINEST, "OpenFlag route trigger: " + Routes.get(j).strategy + " " + Routes.get(j).broker + " " + routeStratType[j] + " @ " + cal.getTime()); | |
openTradeAdjust[i]="YES"; | |
if ("MKT".equals(Orders.get(i).type)) { | |
limitString[i] = "EMSX_LIMIT_PRICE=-99999"; | |
} else { | |
limitString[i] = "EMSX_LIMIT_PRICE=" + String.valueOf(Orders.get(i).limit_price); | |
} | |
newAmount[j] = (int) Math.ceil(.10* Orders.get(i).amount); | |
Routes.get(j).amount = (int) Math.ceil(.10* Orders.get(i).amount); | |
algoInput = new String[]{"EMSX_SEQUENCE=" + String.valueOf(Routes.get(j).sequenceNo), | |
"EMSX_ROUTE_ID=" + String.valueOf(Routes.get(j).routeID), | |
"EMSX_AMOUNT=" + String.valueOf(newAmount[j]), | |
"EMSX_ORDER_TYPE=" + Orders.get(i).type,"EMSX_TIF=DAY", | |
"EMSX_TICKER=" + ticker[i], | |
limitString[i], | |
"EMSX_BROKER=" + Routes.get(j).broker, | |
"ALGO_TYPE=" + openStratType[j]}; | |
ModifyAlgo modOpen = new ModifyAlgo(); | |
if (Testing.isSelected()){ | |
LOGGER.log(Level.FINEST, "TESTING"); | |
} else { | |
modOpen.run(algoInput); | |
} | |
} | |
} else if (shouldModifyRoutePreMarket(i, j)) { | |
// KLT: Since this is real time, we don't need to account for futures expiration. | |
double competingPercentOfOpen = WSTI_ORDER_OBSERVER.getCompetingOpenPercent(primaryTicker[i], ticker[i], TimeFrame.REALTIME); | |
double percentOnOpen = Math.max(0.10, 0.20 - competingPercentOfOpen); | |
AlgorithmRecommendation algorithmRecommendation = AlgorithmRecommendation.from(primaryTicker[i], TimeFrame.REALTIME, Orders.get(i).amount, percentOnOpen, marketDataTable); | |
if (Math.abs(algorithmRecommendation.getOpen() - Routes.get(j).amount) >= 100) { | |
if ("MKT".equals(Orders.get(i).type)) { | |
limitString[i] = "EMSX_LIMIT_PRICE=-99999"; | |
} else { | |
limitString[i] = "EMSX_LIMIT_PRICE=" + String.valueOf(Orders.get(i).limit_price); | |
} | |
newAmount[j] = algorithmRecommendation.getOpen(); | |
algoInput = new String[]{"EMSX_SEQUENCE=" + String.valueOf(Routes.get(j).sequenceNo), | |
"EMSX_ROUTE_ID=" + String.valueOf(Routes.get(j).routeID), | |
"EMSX_AMOUNT=" + String.valueOf(newAmount[j]), | |
"EMSX_ORDER_TYPE=" + Orders.get(i).type, "EMSX_TIF=DAY", | |
"EMSX_TICKER=" + ticker[i], | |
limitString[i], | |
"EMSX_BROKER=" + Routes.get(j).broker, | |
"ALGO_TYPE=" + AlgorithmType.DMA.toString()}; | |
ModifyAlgo modOpen = new ModifyAlgo(); | |
String timestamp = LocalTime.now().format(DateTimeFormatter.ofLocalizedTime(FormatStyle.MEDIUM)); | |
String algorithmInputString = Arrays.toString(algoInput); | |
if (Testing.isSelected()) { | |
try { | |
LOGGER.log(Level.FINEST, "TESTING"); | |
String messagePattern = "%s %s TESTING PREMARKET ORDER ROUTED: %s"; | |
LOGGER.log(Level.FINEST, String.format(messagePattern, exchange[i], timestamp, algorithmRecommendation.toString())); | |
LOGGER.log(Level.FINEST, String.format(messagePattern, exchange[i], timestamp, algorithmInputString)); | |
} catch (Exception ex) { | |
LOGGER.severe(ex.toString()); | |
} | |
} else { | |
LOGGER.log(Level.FINEST, String.format("Competing Open Percent For %s is %.2f", ticker[i], competingPercentOfOpen)); | |
LOGGER.log(Level.FINEST, String.format("Routing %.2f Percent for %s To The Open", percentOnOpen, ticker[i])); | |
String messagePattern = "%s %s LIVE PREMARKET ORDER MODIFICATION ROUTED: %s"; | |
LOGGER.log(Level.FINEST, String.format(messagePattern, exchange[i], timestamp, algorithmRecommendation.toString())); | |
LOGGER.log(Level.FINEST, String.format(messagePattern, exchange[i], timestamp, algorithmInputString)); | |
modOpen.run(algoInput); | |
MODIFICATION_MAP.put(Orders.get(i).sequenceNo, true); | |
} | |
} | |
} else if (sdf.parse(sdf.format(cal.getTime())).after(sdf.parse(closeCutoff[i])) || ("20VWAP".equals(routeStratType[j]) && LocalTime.now().isAfter(openTime[i].toLocalTime().plusMinutes(15)))){ | |
algo[j] = "VWAP"; | |
newLimitPx[j] = Orders.get(i).limit_price; | |
newAmount[j] = Routes.get(j).amount; | |
Algo[i].setText("VWAPe " + newLimitPx[j]); | |
} else if (sdf.parse(sdf.format(cal.getTime())).after(sdf.parse(afterOpen90[i])) && totalArrivalBps > 5 && totalVwapBps > 5 && Orders.get(i).amount/adv10[i] < .04) { //and book is balanced and broad market is good then | |
newLimitPx[j] = lastBasedCalculator.calculate(AlgorithmType.LSA1); | |
algo[j] = "LSA1"; | |
newAmount[j] = Routes.get(j).amount; | |
Algo[i].setText("LSA1t +5s " + newLimitPx[j]); | |
} else if ((("EU".equals(region[i]) && Math.abs(EUbroadMarketChg) > 1) || ("US".equals(region[i]) && Math.abs(broadMarketChg) > 1) || sdf.parse(sdf.format(cal.getTime())).after(sdf.parse(afterOpen60[i])) || (remSell/remBuy > 2 || remBuy/remSell > 2) ) && remBuy + remSell > 1000000 && (remBuy/remSell >1.1 || remSell/remBuy >1.1) && sdf.parse(sdf.format(cal.getTime())).after(sdf.parse(openTimePlus5[i])) && !WSTI_ORDER_OBSERVER.hasWorkingOrder(ticker[i])) { | |
//IMBALANCED | |
basketImbalance = 1; | |
algo[j] = routeStratType[j]; | |
newAmount[j] = Routes.get(j).amount; | |
if (algo[j].startsWith("LSA") && TradingUtils.isLimitAway(Orders.get(i).side, Routes.get(j).limit_price, last[i])) { | |
LimitPriceCalculator calculator = new LimitPriceCalculatorBuilder() | |
.setPrice(last[i]) | |
.setLimit(Orders.get(i).limit_price) | |
.setRoundFactor(roundFactor[i]) | |
.setBps(SLIPPAGE_BPS) | |
.setSide(TradeSideType.from(Orders.get(i).side)) | |
.setType(LAST) | |
.build(); | |
newLimitPx[j] = calculator.calculate(AlgorithmType.LSA1); | |
algo[j] = "LSA1"; | |
} else { | |
newLimitPx[j] = Routes.get(j).limit_price; | |
} | |
if (remBuy/remSell >1.1 && !"YES".equals(imbalanceAdjust[i])) { //buy imbalance | |
if (sideSign[i] == -1) { //reduce buys | |
newAmount[j] = Routes.get(j).amount - (int) ((Math.min(imbalance,remBuy+remSell-1000000)*(remValue[i]/remBuy))/(last[i]*fxRate[i])); | |
LOGGER.log(Level.FINEST, ticker[i] + "\t newAmount[j] = " + newAmount[j] + "\t remV[i]=" + remValue[i] + "\t remBuy=" + remBuy); | |
newLimitPx[j] = lastBasedCalculator.calculate(AlgorithmType.VWAP); | |
algo[j] = "VWAP"; | |
Algo[i].setText("LSA1t + VWAPr"); | |
} else { | |
newAmount[j] = Routes.get(j).amount; | |
newLimitPx[j] = Orders.get(i).limit_price; | |
algo[j] = "VWAP"; | |
Algo[i].setText("VWAPi " + Orders.get(i).limit_price); | |
} | |
} else if (remSell/remBuy >1.1 && !"YES".equals(imbalanceAdjust[i])){ //sell imbalance | |
if (sideSign[i] == 1) { //reduce sells | |
newAmount[j] = Routes.get(j).amount - (int) ((Math.min(-1*imbalance,remBuy+remSell-1000000)*(remValue[i]/remSell))/(last[i]*fxRate[i])); //incorporate imbalance over $1mm | |
LOGGER.log(Level.FINEST, ticker[i] + "\t newAmount[j] = " + newAmount[j] + "\t remV[i]=" + remValue[i] + "\t remSell=" + remSell); | |
newLimitPx[j] = lastBasedCalculator.calculate(AlgorithmType.VWAP); | |
algo[j] = "VWAP"; | |
Algo[i].setText("LSA1t + VWAPr"); | |
} else { | |
newAmount[j] = Routes.get(j).amount; | |
newLimitPx[j] = Orders.get(i).limit_price; | |
algo[j] = "VWAP"; | |
Algo[i].setText("VWAPi " + Orders.get(i).limit_price); | |
} | |
} | |
if (newAmount[j] < Routes.get(j).filled) { | |
newAmount[j] = newAmount[j] + Routes.get(j).filled; | |
} | |
//if book becomes balanced again and there are muliple routes live, then cancel them all | |
// KLT: We want to not cancel the ones that are limit away, because if they are and there route is canceled, is split the VWAP portion again. | |
} else if (openRouteCount[i]>1 && !TradingUtils.isLimitAway(Orders.get(i).side, Orders.get(i).limit_price, last[i])) { | |
LOGGER.log(Level.FINEST, "CANCEL MULTI @" + sdf.format(cal.getTime()) + ": " + openRouteCount[i] + " open routes for " + ticker[i]); | |
Algo[i].setForeground(Color.BLACK);Algo[i].setOpaque(true);Algo[i].setBackground(Color.YELLOW); | |
basketImbalance = 0; | |
algo[j] = routeStratType[j]; | |
newAmount[j] = Routes.get(j).amount; | |
newLimitPx[j] = Routes.get(j).limit_price; | |
Request request = Trigger.emapisvc.createRequest("CancelRoute"); | |
Element routes = request.getElement("ROUTES"); | |
Element route = routes.appendElement(); | |
route.getElement("EMSX_SEQUENCE").setValue(Orders.get(i).sequenceNo); | |
route.getElement("EMSX_ROUTE_ID").setValue(Routes.get(j).routeID); | |
CorrelationID requestID = new CorrelationID("Cancel" + j); | |
if (Testing.isSelected()){ | |
LOGGER.log(Level.FINEST, "TESTING"); | |
} else { | |
Trigger.session.sendRequest(request, requestID); | |
} | |
} else if (trend[i] != null && sdf.parse(sdf.format(cal.getTime())).after(sdf.parse(afterOpen45[i])) && !WSTI_ORDER_OBSERVER.hasWorkingOrder(ticker[i])) { | |
//if broad market is ok and book is balanced after 10:15am... | |
basketImbalance = 0; | |
imbalanceAdjust[i] = "NO"; | |
newAmount[j] = Routes.get(j).amount; | |
newLimitPx[j] = lastBasedCalculator.calculate(AlgorithmType.LSA1); | |
if (!"O".equals(trend[i]) && "F".equals(trend[i].substring(1,2)) && (rsi[i]>80 && bbPerc[i] >.90 || rsi[i]<20 && bbPerc[i] <.10)){ | |
algo[j] = "LSA1"; | |
Algo[i].setText("LSA1t " + newLimitPx[j]); | |
} else if ("BU".equals(trend[i]) && rsi[i]>30 && bbPerc[i] >.20 && volChg1d20d[i] > 125 && bidAskSpread[i] <=0.1 ){ | |
algo[j] = "LSA2"; | |
Algo[i].setText("LSA2t " + newLimitPx[j]); | |
} else if ("SU".equals(trend[i]) && rsi[i]<70 && bbPerc[i] <.80 && volChg1d20d[i] > 125 && bidAskSpread[i] <=0.1 ){ | |
algo[j] = "LSA2"; | |
Algo[i].setText("LSA2t " + newLimitPx[j]); | |
} else if ("O".equals(trend[i]) && favVolumePerc[i] >=25){ | |
LimitPriceCalculator arrivalLimitPriceCalculator = new LimitPriceCalculatorBuilder() | |
.setPrice(Orders.get(i).arrival_price) | |
.setLimit(Orders.get(i).limit_price) | |
.setRoundFactor(roundFactor[i]) | |
.setBps(SLIPPAGE_BPS) | |
.setSide(TradeSideType.from(Orders.get(i).side)) | |
.setType(ARRIVAL) | |
.build(); | |
newLimitPx[j] = arrivalLimitPriceCalculator.calculate(AlgorithmType.LSA1); | |
algo[j] = "LSA1"; | |
Algo[i].setText("LSA1A " + newLimitPx[j]); | |
} else { | |
algo[j] = "VWAP"; | |
newLimitPx[j] = Orders.get(i).limit_price; | |
Algo[i].setText("VWAPb " + Orders.get(i).limit_price); | |
} | |
} else { | |
basketImbalance = 0; | |
if ("VWAP".equals(routeStratType[j]) || "20VWAP".equals(routeStratType[j])) { | |
newLimitPx[j] = Orders.get(i).limit_price; | |
} else { | |
newLimitPx[j] = Routes.get(j).limit_price; | |
} | |
algo[j] = routeStratType[j]; | |
newAmount[j] = Routes.get(j).amount; | |
Algo[i].setText(algo[j] + "x " + newLimitPx[j]); | |
}//end algo[j] if statements | |
//highlight and trade if change is needed | |
if (("YES".equals(openTradeAdjust[i]) || ("20VWAP".equals(routeStratType[j]) && BrokerCode.JEFA.equals(Routes.get(j).broker))) && Orders.get(i).filled > 0 && Routes.get(j).routeID == 1 || newAmount[j] <= 0){ //cancel openflag amount remaining //replace RouteID logic in case user cancels route first | |
LOGGER.log(Level.FINEST, "CANCEL OpenFlag Remain @" + sdf.format(cal.getTime()) + " for " + ticker[i]); | |
Algo[i].setForeground(Color.BLACK);Algo[i].setOpaque(true);Algo[i].setBackground(Color.YELLOW); | |
Request request = Trigger.emapisvc.createRequest("CancelRoute"); | |
Element routes = request.getElement("ROUTES"); | |
Element route = routes.appendElement(); | |
route.getElement("EMSX_SEQUENCE").setValue(Routes.get(j).sequenceNo); | |
route.getElement("EMSX_ROUTE_ID").setValue(Routes.get(j).routeID); | |
LOGGER.log(Level.FINEST, "Request: " + request.toString()); | |
CorrelationID requestID = new CorrelationID("Cancel" + j); | |
if (Testing.isSelected()){ | |
LOGGER.log(Level.FINEST, "TESTING"); | |
} else { | |
Trigger.session.sendRequest(request, requestID); | |
} | |
} else if (((routeStratType[j].equals(algo[j]) || routeStratType[j].equals(algo[j].substring(0,3))) && ((Routes.get(j).limit_price < newLimitPx[j]*1.001 && Routes.get(j).limit_price > newLimitPx[j]*0.9990) || (newLimitPx[j] == 0 && Routes.get(j).limit_price == 0)) && Routes.get(j).amount == newAmount[j]) || "DMA".equals(routeStratType[j]) || "ZVZZT US Equity".equals(ticker[i])) { //already in set algo, do nothing | |
//LOGGER.log(Level.FINEST, "OK: " + ticker[i] + "\t algo[j]:" + algo[j] + " = type[j]: " + routeStratType[j] + "\t Amt[j]: " + Routes.get(j).amount + " = newAmt[j]: " + newAmount[j] + "\t Lmt[j]:" + Routes.get(j).limit_price + " ~= newLmt[j]:" + newLimitPx[j]); | |
if ("LIMIT".equals(Algo[i].getText()) && basketImbalance == 1) { | |
updateImbalanceAlgoText(i); | |
} | |
//LOGGER.log(Level.FINEST, "OK: " + ticker[i] + "\t algo[j]:" + algo[j] + " = type[j]: " + routeStratType[j] + "\t Amt[j]: " + Routes.get(j).amount + " = newAmt[j]: " + newAmount[j] + "\t Lmt[j]:" + Routes.get(j).limit_price + " ~= newLmt[j]:" + newLimitPx[j]); | |
Algo[i].setForeground(Color.WHITE); Algo[i].setBackground(Color.BLACK); //unhighlight | |
} else {//strategy or limit need to be modified | |
LOGGER.log(Level.FINEST, "TRADE @" + sdf.format(cal.getTime()) + " " + ticker[i] + " to " + algo[j]); | |
Algo[i].setForeground(Color.BLACK);Algo[i].setOpaque(true);Algo[i].setBackground(Color.YELLOW); //highlight | |
LOGGER.log(Level.FINEST, "algo[j]: " + algo[j] + "\t type[j]: " + routeStratType[j] + "\t Amt[j]: " + Routes.get(j).amount + "\t newAmt[j]: " + newAmount[j] + "\t Lmt[j]: " + Routes.get(j).limit_price + "\t newLmt[j]: " + newLimitPx[j]); | |
String orderType = OrderTypeStrings.LMT; | |
if (algo[j].startsWith("LSA") || newLimitPx[j] > 0) { | |
limitString[i] = "EMSX_LIMIT_PRICE=" + String.valueOf(newLimitPx[j]); | |
} else { | |
limitString[i] = "EMSX_LIMIT_PRICE=-99999"; | |
orderType = OrderTypeStrings.MKT; | |
} | |
algoInput = new String[]{"EMSX_SEQUENCE=" + String.valueOf(Orders.get(i).sequenceNo), | |
"EMSX_ROUTE_ID=" + String.valueOf(Routes.get(j).routeID), | |
"EMSX_AMOUNT=" + String.valueOf(newAmount[j]), | |
"EMSX_ORDER_TYPE=" + orderType,"EMSX_TIF=DAY", | |
"EMSX_TICKER=" + ticker[i], | |
limitString[i], | |
"EMSX_BROKER=" + Routes.get(j).broker, | |
"ALGO_TYPE=" + algo[j]}; | |
ModifyAlgo modAlgo = new ModifyAlgo(); | |
if (((sideSign[i] == -1 && newLimitPx[j] > Orders.get(i).limit_price && OrderTypeStrings.LMT.equals(Orders.get(i).type)) || (sideSign[i] == 1 && newLimitPx[j] < Orders.get(i).limit_price && OrderTypeStrings.LMT.equals(Orders.get(i).type))) || (newAmount[j] > Orders.get(i).amount) || Testing.isSelected() || ("YES".equals(limitAway[i]) && "VWAP".equals(routeStratType[i]))){ | |
LOGGER.log(Level.FINEST, "TESTING/LIMIT"); | |
} else { | |
modAlgo.run(algoInput); | |
} | |
}//end i if | |
}//end j if | |
}//end of j loop | |
}//end of trade checks ifs | |
} //end of tradecount loop | |
} | |
public void routeOrderToOpen(int i, AlgorithmType algoType, ExecutionModelType model) throws Exception { | |
// route new orders | |
limitString[i] = TradingUtils.limitPrice(Orders.get(i).type, Orders.get(i).limit_price); | |
double percentOfOpenThreshold = TradingUtils.isFuturesExpiration(LocalDate.now()) ? 0.25 : 0.20; | |
double competingPercentOfOpen = WSTI_ORDER_OBSERVER.getCompetingOpenPercent(primaryTicker[i], ticker[i], TimeFrame.HISTORICAL); | |
percentOfOpenThreshold = Math.max(0.10, percentOfOpenThreshold - competingPercentOfOpen); | |
AlgorithmRecommendation algorithmRecommendation = AlgorithmRecommendation.from(primaryTicker[i], TimeFrame.HISTORICAL, Orders.get(i).idle, percentOfOpenThreshold, marketDataTable); | |
int quantity = Orders.get(i).idle; | |
String brokerCode = Orders.get(i).broker; | |
if (algoType == null && BrokerCode.hasTwentyVWAP(brokerCode, Region.create(region[i]))) { | |
algoType = AlgorithmType.TWENTY_VWAP; | |
} else if (algoType == null) { | |
quantity = algorithmRecommendation.getOpen(); | |
algoType = AlgorithmType.DMA; | |
} | |
String orderType = Orders.get(i).type; | |
// if (BrokerCode.MLAL.equals(Orders.get(i).broker) && OrderTypeStrings.MKT.equals(Orders.get(i).type) && algoType == AlgorithmType.TWENTY_VWAP) { | |
// limitString[i] = TradingUtils.relativeCloseLimitPrice(close[i], roundFactor[i], sideSign[i], 0.45); | |
// orderType = OrderTypeStrings.LMT; | |
// } | |
int percentOnOpen = (int) Math.ceil(percentOfOpenThreshold * 100); | |
algoInput = new String[]{"EMSX_SEQUENCE=" + String.valueOf(Orders.get(i).sequenceNo), | |
"EMSX_AMOUNT=" + String.valueOf(quantity), | |
"EMSX_ORDER_TYPE=" + orderType, | |
"EMSX_TIF=DAY", | |
"EMSX_HAND_INSTRUCTION=ANY", | |
"EMSX_TICKER=" + ticker[i], | |
limitString[i], | |
"EMSX_BROKER=" + brokerCode, | |
"ALGO_TYPE=" + algoType.toString(), | |
"EMSX_SIDE=" + Orders.get(i).side, | |
"REGION=" + region[i], | |
"PERCENT_ON_OPEN=" + percentOnOpen | |
}; | |
RouteAlgo routeAlgo = new RouteAlgo(); | |
String timestamp = LocalTime.now().format(DateTimeFormatter.ofLocalizedTime(FormatStyle.MEDIUM)); | |
String algorithmInputString = Arrays.toString(algoInput); | |
String messagePattern = "%s %s TESTING PREMARKET ORDER ROUTED: %s"; | |
if (algoType == AlgorithmType.TWENTY_VWAP) { | |
Algo[i].setText("OPEN" + " " + Orders.get(i).limit_price); | |
} else { | |
Algo[i].setText(algoType.name() + " " + Orders.get(i).limit_price); | |
} | |
Algo[i].setForeground(Color.WHITE); | |
Algo[i].setBackground(Color.BLACK); | |
if (!Testing.isSelected()) { | |
messagePattern = "%s %s LIVE PREMARKET ORDER ROUTED: %s"; | |
Orders.get(i).status = "WORKING"; | |
LOGGER.log(Level.FINEST, String.format("Competing Open Percent For %s is %.2f", ticker[i], competingPercentOfOpen)); | |
LOGGER.log(Level.FINEST, String.format("Routing %d Percent for %s To The Open", percentOnOpen, ticker[i])); | |
routeAlgo.run(algoInput); | |
} | |
if (!LOGS.contains(algorithmInputString)) { | |
LOGGER.log(Level.FINEST, String.format(messagePattern, exchange[i], timestamp, algorithmRecommendation.toString())); | |
LOGGER.log(Level.FINEST, String.format(messagePattern, exchange[i], timestamp, algorithmInputString)); | |
LOGS.add(algorithmInputString); | |
} | |
} | |
public boolean isNotRoutedAndShouldBeRouted(int i) { | |
return TradingUtils.isNotRouted(Orders.get(i).status) && | |
LocalTime.now().isBefore(LocalTime.parse(officialOpenTime[i])) | |
&& marketDataTable.row(primaryTicker[i]).containsKey(Fields.OPENING_VOLUME_AVG) && | |
(Orders.get(i).broker != null); | |
} | |
public boolean isOverrideOnlySelected(int i) { | |
return OverRide[i].isSelected(); | |
} | |
public boolean isOverrideSelected(int i) { | |
return OverRide[i].isSelected() | |
|| "FILLED".equals(Orders.get(i).status) | |
|| "CME".equals(exchange[i]) | |
|| LocalTime.now().isAfter(closeTime[i].toLocalTime()) | |
|| ("YES".equals(limitAway[i]) && Orders.get(i).idle == 0 && LocalTime.now().isBefore(LocalTime.parse(closeCutoff[i]))); | |
} | |
public void setOverrideSelected(int i) { | |
Algo[i].setForeground(Color.GRAY); | |
Algo[i].setBackground(Color.BLACK); | |
if("YES".equals(limitAway[i]) && Orders.get(i).working > 0){ | |
Algo[i].setText("LIMIT"); | |
} else { | |
Algo[i].setText("OUT"); | |
} | |
//checking for idle amounts first (no route[j] logic loops in this part) | |
} | |
public void checkIfOverrideIsSelected() { | |
//check if top override box is checked, that one checks all others | |
if (OverRide[TradeCount].isSelected()){ | |
for (int i=0;i<TradeCount;i++){ | |
OverRide[i].setSelected(true); | |
} | |
selectAll = 1; | |
} else if(!OverRide[TradeCount].isSelected() && selectAll == 1 ) { | |
for (int i=0;i<TradeCount;i++){ | |
OverRide[i].setSelected(false); | |
} | |
selectAll = 0; | |
} | |
} | |
private void updateImbalanceAlgoText(int i) { | |
if (remBuy / remSell > 1.1) { //buy imbalance | |
if (sideSign[i] == -1) { //reduce buys | |
Algo[i].setText("LSA1t + VWAPr"); | |
} else { | |
Algo[i].setText("VWAPi " + Orders.get(i).limit_price); | |
} | |
} else if (remSell / remBuy > 1.1 ) { //sell imbalance | |
if (sideSign[i] == 1) { //reduce sells | |
Algo[i].setText("LSA1t + VWAPr"); | |
} else { | |
Algo[i].setText("VWAPi " + Orders.get(i).limit_price); | |
} | |
} | |
} | |
private boolean shouldModifyRoutePreMarket(int i, int j) { | |
if (algo[j] == null) return false; | |
if (BrokerCode.hasTwentyVWAP(Orders.get(i).broker, Region.create(region[i]))) return false; | |
if (!String.valueOf(marketDataTable.row(ticker[i]).get(BloombergFields.ID_MIC_PRIM_EXCH)).equals("XNYS")) return false; | |
if (MODIFICATION_MAP.containsKey(Orders.get(i).sequenceNo)) return false; | |
if (Orders.get(i).idle == 0) return false; | |
return LocalTime.now().isBefore(LocalTime.parse(officialOpenTime[i])) | |
&& LocalTime.now().isAfter(LocalTime.parse(officialOpenTime[i]) | |
.minusSeconds(15)); | |
} | |
ActionListener screenUpdate = new ActionListener(){ | |
@Override | |
public void actionPerformed(ActionEvent theEvent) { | |
if (myTimerDelay == initialDelayForTickers) { | |
myInitComponents(); | |
myTimer.stop(); | |
myTimerDelay = secondDelayForFX; | |
myTimer = new Timer(myTimerDelay, screenUpdate); | |
myTimer.start(); | |
Trigger.tasvc = Trigger.session.getService(Trigger.service_tasvc); | |
List<String> securityTickers = new ArrayList<>(); | |
//sign up for market data for EMSX tickers, broad market //assign local variables? | |
WeakReference<int[]> vwapWeakReference = new WeakReference<>(FocusGUI.volumeAll); | |
for (int i = 0; i < TradeCount; i++) { | |
List<String> vwapOverrides = new ArrayList<>(); | |
ticker[i] = Orders.get(i).ticker; | |
securityTickers.add(Orders.get(i).ticker); | |
Trigger.mktdata_sub[i] = new Subscription(ticker[i], BloombergConstants.SUBSCRIPTION_FIELDS, new CorrelationID(4 + i)); //need a new correlationID for each ticker | |
Trigger.mktdata_subscriptions.add(Trigger.mktdata_sub[i]); | |
final int finalI = i; | |
vwapOverrides.add("VWAP_START_TIME=" + String.format("%s", LocalTime.MIN.plusSeconds(Orders.get(i).time_stamp))); | |
subscriptionRequestTrigger.subscribe(ticker[i], Arrays.asList(RealtimeField.RT_VWAP_VOLUME), vwapOverrides, (DataChangeEvent e) -> { | |
if (e.getDataName().equals("RT_VWAP_VOLUME")) { | |
vwapWeakReference.get()[finalI] = e.getNewValue().asInt(); | |
} | |
}); | |
} | |
List<String> indexFields = Arrays.asList( | |
"LAST_PRICE", | |
"PRICE_PREVIOUS_CLOSE_RT" | |
); | |
Trigger.mktdata_sub[TradeCount + 1] = new Subscription("SPY US Equity", indexFields, new CorrelationID(4 + TradeCount + 1)); | |
Trigger.mktdata_subscriptions.add(Trigger.mktdata_sub[TradeCount + 1]); | |
Trigger.mktdata_sub[TradeCount + 2] = new Subscription("SXXPIEX GY Equity", indexFields, new CorrelationID(4 + TradeCount + 2)); | |
Trigger.mktdata_subscriptions.add(Trigger.mktdata_sub[TradeCount + 2]); | |
securityTickers.add("SPY US Equity"); | |
securityTickers.add("SXXPIEX GY Equity"); | |
try { | |
Trigger.session.subscribe(Trigger.mktdata_subscriptions); | |
subscriptionRequestTrigger.subscribe(securityTickers, BloombergConstants.REALTIME_SUBSCRIPTION_FIELDS); | |
securityTickers.clear(); | |
} catch (IOException ex) { | |
System.err.println("Failed to create Market Data subscription:" + ex.getMessage()); | |
} | |
//sign up for ref data for EMSX tickers | |
Trigger.refdata = Trigger.session.getService(Trigger.service_refdata); | |
Trigger.request = Trigger.refdata.createRequest("ReferenceDataRequest"); | |
Element securities = Trigger.request.getElement("securities"); | |
for (int i = 0; i < TradeCount; i++) { | |
securities.appendValue(ticker[i]); | |
securityTickers.add(ticker[i]); | |
if ("SW Equity".equals(ticker[i].substring(ticker[i].length() - 9, ticker[i].length()))) { | |
primaryTicker[i] = ticker[i].replace("SW Equity", "SE Equity"); | |
LOGGER.log(Level.FINEST, primaryTicker[i]); | |
} | |
} | |
securities.appendValue("SPY US Equity"); | |
securities.appendValue("SXXPIEX GY Equity"); | |
Element fieldz = Trigger.request.getElement("fields"); | |
BloombergConstants.REFERENCE_REQUEST_FIELDS.forEach(field -> { | |
fieldz.appendValue(field); | |
}); | |
LOGGER.log(Level.FINEST, "Sending Ref Data Request: " + Trigger.request); | |
Trigger.refdata_req_id = new CorrelationID(3); | |
try { | |
referenceRequestTrigger.submit(securityTickers, BloombergConstants.REFERENCE_REQUEST_FIELDS, Map.of("EQY_FUND_CRNCY", "USD")); | |
Trigger.session.sendRequest(Trigger.request, Trigger.refdata_req_id); | |
} catch (IOException ex) { | |
LOGGER.log(Level.SEVERE, ex.getMessage()); | |
} | |
//sign up for ref tick data for EMSX tickers, using primary tickers for SW names | |
Trigger.refdata = Trigger.session.getService(Trigger.service_refdata); | |
Trigger.request = Trigger.refdata.createRequest("ReferenceDataRequest"); | |
Element tickSecurities = Trigger.request.getElement("securities"); | |
for (int i = 0; i < TradeCount; i++) { | |
if (ticker[i].endsWith("SW Equity")) { | |
primaryTicker[i] = ticker[i].replace("SW Equity", "SE Equity"); | |
LOGGER.log(Level.FINEST, primaryTicker[i]); | |
} else { | |
primaryTicker[i] = ticker[i]; | |
} | |
tickSecurities.appendValue(primaryTicker[i]); | |
} | |
Element flds = Trigger.request.getElement("fields"); | |
flds.appendValue("reference tick size"); | |
LOGGER.log(Level.FINEST, "Sending Ref Tick Data Request: " + Trigger.request); | |
Trigger.reftick_req_id = new CorrelationID(33333333); | |
try { | |
Trigger.session.sendRequest(Trigger.request, Trigger.reftick_req_id); | |
} catch (IOException ex) { | |
LOGGER.log(Level.SEVERE, ex.getMessage()); | |
} | |
} else if (myTimerDelay == secondDelayForFX) { //need the second delay to pick up FX/region/DVD data from initial sub | |
for (int i = 0; i < TradeCount; i++) { | |
if ("G3".equals(pilotGroup[i]) || "G2".equals(pilotGroup[i]) || "G1".equals(pilotGroup[i])) { | |
roundFactor[i] = 20; | |
} else { | |
roundFactor[i] = 100; | |
} | |
if ("GBp".equals(currency[i])) { | |
currencyTicker[i] = "GBPUSD Curncy"; | |
CurrArray.add(currencyTicker[i]); | |
LOGGER.log(Level.FINEST, "Currency Test: " + currency[i]); | |
} else if (!"USD".equals(currency[i])) { | |
currencyTicker[i] = currency[i] + "USD Curncy"; | |
LOGGER.log(Level.FINEST, "Currency Test: " + currency[i]); | |
CurrArray.add(currencyTicker[i]); | |
} else { | |
fxRate[i] = 1; | |
} | |
if (!"USD".equals(currency[i]) && !"CAD".equals(currency[i])) { | |
TradingCalendar tradingCalendar; | |
if ("NOK".equals(currency[i])) { | |
tradingCalendar = new XoslExchangeCalendar(); | |
} else if ("DKK".equals(currency[i])) { | |
tradingCalendar = new XcseExchangeCalendar(); | |
} else if ("PLN".equals(currency[i])) { | |
tradingCalendar = new XwarExchangeCalendar(); | |
} else { | |
tradingCalendar = new XlonExchangeCalendar(); | |
} | |
openTime[i] = LocalDateTime.parse(String.valueOf(today.format(cal.getTime())) + " " + tradingCalendar.easternTime(TradingEvent.OPEN), formatter); | |
closeTime[i] = LocalDateTime.parse(String.valueOf(today.format(cal.getTime())) + " " + tradingCalendar.easternTime(TradingEvent.CLOSE), formatter); | |
fullDay[i] = (double) Duration.between(openTime[i], closeTime[i]).toMinutes(); | |
officialOpenTime[i] = tradingCalendar.easternTime(TradingEvent.OPEN); | |
openTimePlus5[i] = tradingCalendar.easternTime(TradingEvent.OPEN_PLUS_FIVE); | |
openTimePlus10[i] = tradingCalendar.easternTime(TradingEvent.OPEN_PLUS_TEN); | |
startTechStudies[i] = tradingCalendar.easternTime(TradingEvent.START_TECH_STUDIES); | |
afterOpen45[i] = tradingCalendar.easternTime(TradingEvent.AFTER_OPEN_FORTY_FIVE); | |
afterOpen60[i] = tradingCalendar.easternTime(TradingEvent.AFTER_OPEN_SIXTY); | |
afterOpen90[i] = tradingCalendar.easternTime(TradingEvent.AFTER_OPEN_NINETY); | |
region[i] = "EU"; | |
marketDataTable.put(ticker[i], "region", TypedObject.of("EU")); | |
closeCutoff[i] = tradingCalendar.easternTime(TradingEvent.CLOSE_CUTOFF); | |
roundFactor[i] = TradingUtils.roundFactor(refTickSize[i]); | |
LOGGER.log(Level.FINEST, String.format("%s %s", TradingEvent.OPEN, openTime[i])); | |
LOGGER.log(Level.FINEST, String.format("%s %s", TradingEvent.CLOSE_CUTOFF, closeCutoff[i])); | |
LOGGER.log(Level.FINEST, String.format("%s %s", TradingEvent.CLOSE, closeTime[i])); | |
LOGGER.log(Level.FINEST, String.format("%s %s", TradingEvent.OPEN_PLUS_FIVE, openTimePlus5[i])); | |
LOGGER.log(Level.FINEST, String.format("%s %s", TradingEvent.START_TECH_STUDIES, startTechStudies[i])); | |
LOGGER.log(Level.FINEST, String.format("%s %s", TradingEvent.AFTER_OPEN_FORTY_FIVE, afterOpen45[i])); | |
LOGGER.log(Level.FINEST, String.format("%s %s", TradingEvent.AFTER_OPEN_SIXTY, afterOpen60[i])); | |
LOGGER.log(Level.FINEST, String.format("%s %s", TradingEvent.AFTER_OPEN_NINETY, afterOpen90[i])); | |
} else { | |
openTime[i] = LocalDateTime.parse(String.valueOf(today.format(cal.getTime())) + " 09:30:00", formatter); | |
closeTime[i] = LocalDateTime.parse(String.valueOf(today.format(cal.getTime())) + " 16:00:00", formatter); | |
fullDay[i] = (double) Duration.between(openTime[i], closeTime[i]).toMinutes(); | |
officialOpenTime[i] = "09:30:00"; | |
openTimePlus5[i] = "09:35:00"; | |
openTimePlus10[i] = "09:40:00"; | |
startTechStudies[i] = "10:13:00"; | |
afterOpen45[i] = "10:15:00"; | |
afterOpen60[i] = "10:30:00"; | |
afterOpen90[i] = "11:00:00"; | |
if (halfDays.contains(cal.getTime())) { | |
closeCutoff[i] = "12:35:00"; | |
} else { | |
closeCutoff[i] = "15:35:00"; | |
} | |
region[i] = "US"; | |
marketDataTable.put(ticker[i], "region", TypedObject.of("US")); | |
String exchangeCode = ""; | |
if (marketDataTable.row(ticker[i]).containsKey(BloombergFields.EQY_PRIM_EXCH_SHRT)) { | |
exchangeCode = marketDataTable.row(ticker[i]).get(BloombergFields.EQY_PRIM_EXCH_SHRT).asString(); | |
} else if (marketDataTable.row(ticker[i]).containsKey(BloombergFields.EXCH_CODE)) { | |
exchangeCode = marketDataTable.row(ticker[i]).get(BloombergFields.EXCH_CODE).asString(); | |
} | |
if (ticker[i].endsWith("US Equity")) { | |
primaryTicker[i] = ticker[i].replace("US Equity", String.format("%s Equity", exchangeCode)); | |
} else if (ticker[i].endsWith("CN Equity")) { | |
primaryTicker[i] = ticker[i].replace("CN Equity", String.format("%s Equity", exchangeCode)); | |
} else { | |
primaryTicker[i] = ticker[i]; | |
} | |
} | |
} | |
try { | |
List<String> primaryTickers = new ArrayList<>(); | |
for (int i = 0; i < TradeCount; i++) { | |
TICKER_TO_PRIMARY_TICKER.put(ticker[i], primaryTicker[i]); | |
marketDataTable.put(ticker[i], "primary", TypedObject.of(primaryTicker[i])); | |
primaryTickers.add(primaryTicker[i]); | |
} | |
LOGGER.log(Level.FINEST, "Primary Tickers: " + primaryTickers); | |
subscriptionRequestTrigger.subscribe(primaryTickers, Arrays.asList( | |
RealtimeField.VOLUME_THEO, | |
RealtimeField.PX_OFFICIAL_AUCTION_RT, | |
RealtimeField.IN_AUCTION_RT, | |
RealtimeField.AUCTION_TYPE_REALTIME, | |
RealtimeField.TIME_AUCTION_CALL_CONCLUSION_RT | |
)); | |
referenceRequestTrigger.retrieveOpenAuctionVolumes(primaryTickers, 24); | |
} catch (Exception e) { | |
LOGGER.log(Level.SEVERE, e.getMessage()); | |
} | |
myTimer.stop(); | |
myTimerDelay = screenRefresh; | |
myTimer = new Timer(myTimerDelay, screenUpdate); | |
myTimer.start(); | |
//timer for technical analysis studies and custom vwap functions | |
studyTimer = new Timer(studyTimerDelay, studyUpdate); | |
studyTimer.start(); | |
studyUpdate.actionPerformed(theEvent); | |
//fx refdata | |
if (CurrArray.size() > 0) { | |
Trigger.request = Trigger.refdata.createRequest("ReferenceDataRequest"); | |
Element securities = Trigger.request.getElement("securities"); | |
Element fxFieldz = Trigger.request.getElement("fields"); | |
fxFieldz.appendValue("PX_YEST_CLOSE"); | |
fxFieldz.appendValue("LAST_PRICE"); //needs to be last? make sure if you add new refdata | |
Trigger.fx_req_id = new CorrelationID(TradeCount + 7); | |
for (String s : CurrArray) { | |
securities.appendValue(s); | |
} | |
referenceRequestTrigger.submit(CurrArray, Arrays.asList( | |
"PX_YEST_CLOSE", | |
"LAST_PRICE" | |
), Map.of()); | |
LOGGER.log(Level.FINEST, "Sending FX Data Request: " + Trigger.request); | |
try { | |
Trigger.session.sendRequest(Trigger.request, Trigger.fx_req_id); | |
} catch (IOException ex) { | |
LOGGER.log(Level.SEVERE, ex.getMessage()); | |
} | |
} | |
} else { //applies for the screenRefresh timer delay | |
try { | |
updateBlotter(); | |
} catch (ParseException ex) { | |
LOGGER.log(Level.SEVERE, ex.getMessage()); | |
} | |
try { | |
String value = System.getProperty("portfolio", "focus"); | |
if ("focus".equals(value) || "focus_us".equals(value)) { | |
tradeLogic(); | |
} else if ("pairs".equals(value)) { | |
pairsTradeLogic2(); | |
} else if ("a_plus".equals(value)) { | |
aplusTradeLogic(); | |
} else if ("ds".equals(value)) { | |
dsTradeLogic(); | |
} | |
} catch (ParseException ex) { | |
LOGGER.log(Level.SEVERE, ex.getMessage()); | |
} catch (Exception ex) { | |
LOGGER.log(Level.SEVERE, ex.getMessage()); | |
} | |
} | |
} | |
}; | |
ActionListener studyUpdate = new ActionListener(){ | |
@Override | |
public void actionPerformed (ActionEvent theEvent) { | |
//technical analysis update; needs DST updates for bloomberg's GMT conversion | |
Calendar local = Calendar.getInstance(); | |
for (int i=0;i<TradeCount;i++){ | |
try { | |
if (!"FILLED".equals(Orders.get(i).status) && Orders.get(i).arrival_price != 0 && sdf.parse(sdf.format(local.getTime())).after(sdf.parse(startTechStudies[i])) && !vwapSent[i] && sdf.parse(sdf.format(local.getTime())).before(sdf.parse(closeCutoff[i]))){ //vwap sub | |
LOGGER.log(Level.FINEST, "Mkt VWAP Sub Starting"); | |
List<RealtimeField> vwapFields = Arrays.asList( | |
RealtimeField.VWAP, | |
RealtimeField.RT_VWAP_VOLUME, | |
RealtimeField.MARKET_DEFINED_VWAP_REALTIME, | |
RealtimeField.RT_MKT_VWAP_VOLUME | |
); | |
WeakReference<double[]> vwapWeakReference = new WeakReference<>(FocusGUI.favVolume); | |
for (int j=0; j<TradeCount; j++) { | |
List<String> vwapOverrides = new ArrayList<>(); | |
if (!"FILLED".equals(Orders.get(j).status) && FocusGUI.Orders.get(j).arrival_price != 0){ | |
vwapOverrides.add("VWAP_START_TIME=" + String.format("%s", LocalTime.MIN.plusSeconds(Orders.get(j).time_stamp))); | |
if ("SELL".equals(Orders.get(j).side) || "SHRT".equals(Orders.get(j).side)) { | |
vwapOverrides.add("VWAP_MIN_PX=" + String.format("%.2f", Math.max(FocusGUI.Orders.get(j).arrival_price, FocusGUI.Orders.get(j).limit_price))); | |
} else { | |
vwapOverrides.add("VWAP_MAX_PX=" + String.format("%.2f", Math.min(FocusGUI.Orders.get(j).arrival_price, FocusGUI.Orders.get(j).limit_price > 0 ? FocusGUI.Orders.get(j).limit_price : Double.MAX_VALUE))); //need to clear this field after? | |
} | |
final int finalJ = j; | |
vwapTrigger.subscribe(FocusGUI.ticker[j], vwapFields, vwapOverrides, (DataChangeEvent e) -> { | |
if (e.getDataName().equals("RT_VWAP_VOLUME")) { | |
vwapWeakReference.get()[finalJ] = e.getNewValue().asDouble(); | |
} | |
}); | |
vwapSent[j] = true; | |
LOGGER.log(Level.FINEST, String.format("Mkt VWAP Sub %s", FocusGUI.ticker[j])); | |
} | |
} | |
} | |
if (!"FILLED".equals(Orders.get(i).status) && sdf.parse(sdf.format(local.getTime())).after(sdf.parse(startTechStudies[i])) && sdf.parse(sdf.format(local.getTime())).before(sdf.parse(closeCutoff[i])) && !"YES".equals(limitAway[i]) ){ //do not request if already filled or outside limit | |
IntradayStudyRequestBuilder builder = new IntradayStudyRequestBuilder(ticker[i], | |
OffsetDateTime.now().minusMinutes(8), | |
OffsetDateTime.now()) | |
.setChoice("bollStudyAttributes") | |
.setPeriod(20) | |
.setLowerBand(2) | |
.setPriceSourceClose("close") | |
.setUpperBand(2); | |
CompletableFuture<IntradayStudyData> future = intradayStudyTrigger.submit(builder); | |
final int finalI = i; | |
WeakReference<double[]> weakReference = new WeakReference<>(FocusGUI.bbPerc); | |
future.thenAccept(studyData -> { | |
for (OffsetDateTime date : studyData.get().rowKeySet()) { | |
weakReference.get()[finalI] = studyData.get().row(date).get(IntradayStudyField.BB_PERCENT).asDouble(); | |
} | |
}); | |
// RSI Study, do not request if order is already filled | |
IntradayStudyRequestBuilder rsiStudyBuilder = new IntradayStudyRequestBuilder(ticker[i], | |
OffsetDateTime.now().minusMinutes(8), | |
OffsetDateTime.now()) | |
.setChoice("rsiStudyAttributes") | |
.setPeriod(14) | |
.setPriceSourceClose("close"); | |
WeakReference<double[]> rsiWeakReference = new WeakReference<>(FocusGUI.rsi); | |
CompletableFuture<IntradayStudyData> rsiFuture = intradayStudyTrigger.submit(rsiStudyBuilder); | |
rsiFuture.thenAccept(studyData -> { | |
for (OffsetDateTime date : studyData.get().rowKeySet()) { | |
rsiWeakReference.get()[finalI] = studyData.get().row(date).get(IntradayStudyField.RSI).asDouble(); | |
} | |
}); | |
} | |
} catch (ParseException ex) { | |
LOGGER.log(Level.SEVERE, ex.getMessage()); | |
} catch (Exception ex) { | |
LOGGER.log(Level.SEVERE, ex.getMessage()); | |
} | |
} | |
} | |
}; | |
public static void main(String args[]) throws Exception{ | |
Trigger.run(); | |
vwapTrigger.run(); | |
SessionOptions sessionOptions = new SessionOptions(); | |
sessionOptions.setServerPort(8194); | |
sessionOptions.setServerHost("localhost"); | |
DefaultBloombergSession session = new DefaultBloombergSession(sessionOptions); | |
session.start(); | |
WstiAggregator aggregator1 = new WstiAggregator(session, WSTI_ORDER_OBSERVER); | |
aggregator1.run(); | |
try { | |
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) { | |
if ("Windows".equals(info.getName())) { | |
javax.swing.UIManager.setLookAndFeel(info.getClassName()); | |
break; | |
} | |
} | |
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | javax.swing.UnsupportedLookAndFeelException ex) { | |
LOGGER.log(Level.SEVERE, ex.getMessage()); | |
} | |
java.awt.EventQueue.invokeLater(FocusGUI::new); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment