//signal requests to reverse the order and calls schedule signal on each.
if (request.command()== Command.Reverse) {
Integer existingQuantity = portfolio.position(symbol).quantity();
Request requestToClose = buildBaseRequest(request,existingQuantity,symbol);
if (existingQuantity>0) {
//STC
requestToClose.put(Parameter.Action, SignalAction.STC);
} else {
//BTC
requestToClose.put(Parameter.Action, SignalAction.BTC);
}
//schedule the closing request
int[] parentId = scheduleSignal(timeToExecute,requestToClose);
//previous closed now reverse
//only fields needed for building all-in-one dependent signals
Request requestToOpen = buildBaseRequest(request,existingQuantity,symbol);
if (existingQuantity>0) {
//STO
requestToClose.put(Parameter.Action, SignalAction.STO);
} else {
//BTO
requestToClose.put(Parameter.Action, SignalAction.BTO);
}
//schedule the opening request
return scheduleSignal(timeToExecute,requestToClose);
} else {
//use to compute quantity
QuantityComputable quantityComputable = quantityFactory.computable(request,this);
//GTC or Day
Duration timeInForce = (Duration)request.get(Parameter.TimeInForce);
//cancel at this fixed time
long cancelAtMs = Long.MAX_VALUE;
Number cancelAt = (Number)request.get(Parameter.CancelsAt);
if (cancelAt != null) {
cancelAtMs = 1000l * cancelAt.intValue();
}
Number cancelAtRelative = (Number)request.get(Parameter.CancelsAtRelative);
if (cancelAtRelative != null) {
cancelAtMs = timeToExecute + (1000l * cancelAtRelative.intValue());
}
assert(request.command() == Command.Signal);
Instrument instrument = (Instrument)request.get(Parameter.Instrument);
action = (SignalAction)request.get(Parameter.Action);
Integer xReplace = (Integer)request.get(XReplace);
if (xReplace!=null) {
if (xReplace<0 || (xReplace>>BITS_FOR_SYSTEM_ID)>=archive.size()) {
throw new C2ServiceException("Invalid signalId "+xReplace+" not found.",false);
}
Order oldOrder = archive.get(xReplace>>BITS_FOR_SYSTEM_ID);
oldOrder.cancelOrder(timeToExecute);//cancel old order to be replaced
conditionalUponOrder = oldOrder.conditionalUpon();
assert(conditionalUponOrder!=null);
assert(conditionalUponOrder.quantity()>0 || conditionalUponOrder.isPending());
}
Order signal;
//convert everything to relatives, should have already been relatives?
RelativeNumber limit = (RelativeNumber)request.get(Parameter.RelativeLimitOrder);
if (limit != null) {
OrderProcessor limitProcessor = new OrderProcessorLimit(timeToExecute, symbol,limit);
signal = new Order(this, id, instrument, symbol, action, quantityComputable, cancelAtMs, timeInForce,limitProcessor,conditionalUponOrder);
} else {
RelativeNumber stop = (RelativeNumber)request.get(Parameter.RelativeStopOrder);
if (stop != null) {
OrderProcessor stopProcessor = new OrderProcessorStop(timeToExecute, symbol,stop);
signal = new Order(this, id, instrument, symbol, action, quantityComputable, cancelAtMs, timeInForce, stopProcessor,conditionalUponOrder);
} else {
//market
OrderProcessor marketProcessor = new OrderProcessorMarket(timeToExecute, symbol);
signal = new Order(this, id, instrument, symbol, action, quantityComputable, cancelAtMs, timeInForce, marketProcessor,conditionalUponOrder);
}
}
Integer ocaId = (Integer)request.get(OCAId);
if (ocaId!=null) {
signal.oneCancelsAnother(ocaId);
//add this signal to the group under this ocaId
ocaMap.get(ocaId).add(signal);
}
order = signal;
}
//must be done before adding the all-in-one stop or target because they must also be added
archive.add(order);//needed for long term lookup by id order
scheduled.add(order);//needed for processing by time order
Integer ocaId = null;
RelativeNumber stopLoss = (RelativeNumber)request.get(Parameter.RelativeStopLoss);
RelativeNumber profitTarget = (RelativeNumber)request.get(RelativeProfitTarget);
Integer forceNoOCA = (Integer)request.get(ForceNoOCA);
if ((forceNoOCA==null || forceNoOCA.intValue()!=1) && (null!=stopLoss) && (null!=profitTarget)) {
ocaId = generateNewOCAId();
}
int stopLossSignalId = NO_ID;
int profitTargetSignalId = NO_ID;
//generate and schedule requests for all-in-one
if (stopLoss!=null) {
Request stopRequest = request.baseConditional();
//all in one stopLoss, this is sell to close on buy and buy to close on sell.
if (action == SignalAction.BTO) {
stopRequest.put(Parameter.Action, SignalAction.STC);
} else if (action == SignalAction.SSHORT || action == SignalAction.STO) {
stopRequest.put(Parameter.Action, SignalAction.BTC);
} else {
throw new UnsupportedOperationException("ActionType:"+action+" all-in-on stop loss undefined");
}
stopRequest.put(Parameter.RelativeStopOrder,stopLoss);
//this is the only place the code will be able to get quantity because it can not be set
//here when Dollar or Percent is used.
stopRequest.put(Parameter.ConditionalUpon,id);
//get quantity after previous order is submitted, must have exact shares!
if (ocaId!=null) {
stopRequest.put(Parameter.OCAId,ocaId);
}
stopLossSignalId = scheduleSignal(timeToExecute, stopRequest)[0];
//must return <stoplosssignalid>35584025</stoplosssignalid>
}
//generate and schedule requests for all-in-one
if (profitTarget!=null) {
Request profitTargetRequest = request.baseConditional();
if (action == SignalAction.BTO) {
profitTargetRequest.put(Parameter.Action, SignalAction.STC);
} else if (action == SignalAction.SSHORT || action == SignalAction.STO) {
profitTargetRequest.put(Parameter.Action, SignalAction.BTC);
} else {
throw new UnsupportedOperationException("ActionType:"+action+" all-in-on stop loss undefined");
}
profitTargetRequest.put(Parameter.RelativeLimitOrder,profitTarget);
//this is the only place the code will be able to get quantity because it can not be set
//here when Dollar or Percent is used.
profitTargetRequest.put(Parameter.ConditionalUpon,id);
//get quantity after previous order is submitted, must have exact shares!
if (ocaId!=null) {
profitTargetRequest.put(Parameter.OCAId,ocaId);
}
profitTargetSignalId = scheduleSignal(timeToExecute, profitTargetRequest)[0];
//must return <profittargetsignalid>35584025</profittargetsignalid>