How to submit signals to C2

Definitions

First, let’s look at all the available fields and what they represent. The JSON body of the request requires a “Order” property containing some, and sometimes all of the following members:

Member name Required Type Description
StrategyId Mandatory integer Your C2 StrategyId. You can find your trading system’s ID number above the system’s name on the main system page
OrderType Mandatory string The type of signal. “1” = Market, “2” = Limit, “3” = Stop
Side Mandatory string “1” = Buy, “2” = Sell
OrderQuantity Mandatory decimal The order quantity
Limit Optional decimal The Limit Price
Stop Optional decimal The Stop Price
TIF Mandatory string The time in force. “0” = Day, “1” = Good Till Cancel (GTC)
CancelReplaceSignalId Optional integer Used to specify that this signal replaces another
ParentSignalId Optional integer Used to specify that this order is conditional (a child) on another
DoNotSyncToOpen Optional Boolean Used to indicate this order should not be synched in the brokerage account. Only applies to Opening non-market orders. See https://collective2.com/about-do-not-follow-to-open
StopLoss Optional integer Only available in NewStrategyOrder endpoint. The C2-formatted Price at which to place a exit order conditional on the parent
ProfitTarget Optional integer Only available in NewStrategyOrder endpoint. The C2-formatted Price at which to place a exit order conditional on the parent
DoNotCreateOCAGroup Optional Boolean Used to indicate that C2 should not create a OCA group with the ProfitTarget and StopLoss signals (if they are present above)
C2Symbol Optional Object The symbol in C2 format. Either C2Symbol or ExchangeSymbol must be present to indicate the symbol you want to trade
{ FullSymbol Mandatory string The C2 native symbol e.g. “@ESM23”
SymbolType Mandatory string The type of instrument. e.g. “stock”, “option”, “future”, “forex”
Underlying Optional string Stock Option Underlying symbol e.g. “MSFT” Expiry Optional string Stock Option expiry. Format is “May23”
PutOrCall Optional string Stock Option “put” or “call” StrikePrice Optional decimal Stock Option strike price }
ExchangeSymbol Optional Object The symbol in native exchange format. Either C2Symbol or ExchangeSymbol must be present to indicate the symbol you want to trade {
Symbol Mandatory string The native exchange symbol e.g. “ESM23”
Currency Mandatory string The 3-character ISO instrument currency. E.g. “USD”
SecurityExchange Mandatory string The ISO Exchange code e.g. DEFAULT (for stocks & options), XCME, XEUR, XICE, XLIF, XNYB, XNYM, XASX, XCBF, XCBT, XCEC, XKBT, XSES. See details at http://www.iso15022.org/MIC/homepageMIC.htm
SecurityType Mandatory string The SecurityType e.g. “CS”, “FUT”, “OPT”, “FOR”
MaturityMonthYear Mandatory string The MaturityMonthYear in YYYYMM format e.g. “202303”, or if the contract requires a day: “20230521”
PutOrCall Mandatory integer The Option PutOrCall e.g. 0 = Put, 1 = Call }

Simple Signal

Here is an example API request for a simple signal:
It tells C2 to SELL SHORT 5 contracts of the June 2023 E-Mini S&P futures contract, at 4199.25 limit. The order is a DAY signal:

Request:

                
  {
    "Order":
    {
        "StrategyId":           89959688,
        "OrderType":            "2",
        "Side":                 "2",
        "OrderQuantity":        5,
        "Limit":                "4199.25",
        "TIF":                  "0",
        "C2Symbol":
        {
            "FullSymbol":       "@ESM23",
            "SymbolType":       "future"
        }
    }
  }
                
              

Response:

                
  {
    "Results":
    [
        {
            "SignalId": 144260505
        }
    ],
    "ResponseStatus":
    {
        "ErrorCode": "200"
    }
  }
                
              

There are a few important things to notice about the C2 response. First, C2 tells me whether the API request I made triggered any sort of error, or if it was ok. In this case, the signal request was accepted, because ResponseStatus was 200. Notice also that C2 returned a SignalId number for me (144260505). This is useful because with this number I can refer to the signal in subsequent calls. For example, I can cancel-replace the signal (i.e. change the limit price from 4199.25 to some other value), or cancel it completely. Variations on Signals You can submit market signals, limit signals, or stop signals. Here I submit a market signal to buy to open (BTO) 2 shares of IBM stock at the market. The following is a DAY signal:

Request:

                
  {
    "Order":
    {
        "StrategyId":           116881082,
        "OrderType":            "1",
        "Side":                 "1",
        "OrderQuantity":        2,
        "TIF":                  "0",
        "ExchangeSymbol":
        {
            "Symbol":           "IBM",
            "Currency":         "USD",
            "SecurityType":     "CS"
        }
    }
  }
                
              

Here is a signal to buy at limit price 130.22, good until cancel (GTC):

Request:

                
  {
    "Order":
    {
        "StrategyId":           116881082,
        "OrderType":            "2",
        "Side":                 "1",
        "OrderQuantity":        2,
        "Limit":                130.22,
        "TIF":                  "1",
        "ExchangeSymbol":
        {
            "Symbol":           "IBM",
            "Currency":         "USD",
            "SecurityType":     "CS"
        }
    }
  }
                
              

Conditional Signals

Once you know a SignalId, it is easy to create a conditional signal. A conditional signal is an order that becomes valid only once the original (parent) signal is traded. To create a conditional signal, include a parameter: ParentSignalId. Like this:

Request:

                
  {
    "Order":
    {
        "StrategyId":           116881082,
        "OrderType":            "2",
        "Side":                 "2",
        "OrderQuantity":        2,
        "Limit":                135,
        "TIF":                  "2",
        "ParentSignalId":       144260639,
        "ExchangeSymbol":
        {
            "Symbol":           "IBM",
            "Currency":         "USD",
            "SecurityType":     "CS"
        }
    }
  }
                
              

Bracket Signals (Entry + Stop Loss + Profit Target)

It’s a pain in the ass to create an entry signal as a “parent,” then two separate conditional child signals: a stop-loss and a profit target. Why not do it all in one swoop? Like this:

Request:

                
  {
    "Order":
    {
        "StrategyId":           116881082,
        "OrderType":            "1",
        "Side":                 "1",
        "OrderQuantity":        2,
        "TIF":                  "0",
        "ProfitTarget":         1.22,
        "StopLoss":             0.999,
        "C2Symbol":
        {
            "FullSymbol":       "EURUSD",
            "SymbolType":       "forex"
        }
    }
  }
                
              

Response:

                
  {
    "Results":
    [
        {
            "SignalId":              144261816,
            "ProfitTargetSignalId":  144261818,
            "StopLossSignalId":      144261820,
            "ExitSignalsOCAGroupId": 144261817
        }
    ],
    "ResponseStatus":
    {
        "ErrorCode": "200"
    }
  }
                
              

The stop loss and profit target are each assigned a separate SignalId by C2 (144261820 and 144261818 respectively), and thus can be referred to later. (For example, perhaps you will want to adjust your stop loss?)

You will also notice C2 created a One-Cancels-All (OCA) group (ExitSignalsOCAGroupId = 144261817). The profit target and stop loss are both part of the same OCA group. This means that when one is canceled, expired, or traded, the other is canceled.

If you don’t want C2 to automatically group your bracket orders into an OCA group, just include the following parameter in your Order property: “DoNotCreateOCAGroup”: true

Cancel-and-Replace (xreplace) Signals

It is common to change a working signal’s price. For instance, you might want to change the limit price of your profit target, which has not yet been reached; or the stop price of not-yet-triggered stop loss. Rather than requiring two steps to achieve this (by first, canceling a specific signal; and second, submitting a replacement order), you can achieve the same functionality in one step, by using the parameter called cancel-and-replace, or xreplace. Here we change the ProfitTarget limit order from the previous example:

                
  {
      "Order":
      {
          "StrategyId":           116881082,
          "OrderType":            "2",
          "Side":                 "2",
          "OrderQuantity":        2,
          "OpenClose":            "C",
          "TIF":                  "1",
          "Limit":                1.011,
          "CancelReplaceSignalId": 144261818,
          "C2Symbol":
          {
              "FullSymbol":       "EURUSD",
              "SymbolType":       "forex"
          }
      }
  }