Hello everyone,
In my feedback on CTS's earlier drafts, I suggested a standardized set of semantical errors part of each CTS response message. For example, when an actor submits a tender (i.e., EiCreateTender) to the market for a non-tradeable instrument, the market must reject the tender and include the error code indicating the rejection reason in the response (i.e., EiCreatedTender). This set of standardized semantical errors empowers practical standard-based interoperability beyond just the "happy-path" case.
As a sideline, also note that the name of the response message is misleading since it did not create the tender but instead rejected it. Perhaps a name like EiCreateTenderResponse would be more appropriate.
To provide additional context, I am sharing an example of the possible error codes with their meanings and variants we (ResilientEnergy.com) implemented when the market exchange rejects a tender from a market participant:
Tender Rejection Types:
public enum RejectionType
{
Undefined,
MarketClosed,
ParticipantBan,
RulesViolation,
CircuitBreaker,
DuplicateTender,
InvalidTender,
ForceMajeure
}
Rejection Type Enum values description:
The RejectionReason.RejectionType property indicates why the managing exchange rejected the market request or an individual tender. The RejectionType is an enum that lists the possible reasons for rejection.
The RejectionType.Undefined is the default rejection reason. The managing exchange only uses the Undefined for DTO initialization and as a fallback if it cannot use any other value. The managing exchange logs a warning before sending a market response with RejectionType.Undefined.
The RejectionType.MarketClosed is the rejection reason the managing exchange responds with when a participant makes a market request in a closed market. The participant exchange caches the market status and disallows some market requests in a closed market (e.g., submit tenders). A participant exchange can receive this rejection type if its local market status flag is not up to date (i.e., the participant missed an earlier On Closed Market Event).
The RejectionType.ParticipantBan is the rejection reason the managing exchange responds with when a participant makes a market request that its participant status forbids. A restriction on a participant's status can vary from a complete trading ban in any market to a partial ban restricting the amount of power and the instruments a participant can sell or buy. The rejected reason the participant exchange receives does not provide complete details on a participant's status. Instead, when receiving a rejection reason of RejectionType.ParticipantBan, the participant, posts a status market request for an up-to-date participant status (see Participant Status Market Request section). The participant exchange stores locally a copy of its participant status in each marketplace and validates any request and against it before posting the request to the market. A participant exchange can receive this rejection type if its local participant status is not up to date (i.e., the participant missed an earlier Participant Status Market Response).
The managing exchange sets the rejection type to RejectionType.RulesViolation when either the participant request or an individual tender violates the market or marketplace rules. Since, the participant exchange stores a local copy of the rules which it uses to pre-validate requests and tenders, receiving the RejectionType.RulesViolation is an indication of a stale local copy of the rules. In this case, the participant exchange posts a status market request to the managing exchange to request the latest rules (see Participant Status Market Request section). This can happen if the participant exchange did not receive the market rules announcement when the managing exchange posted it (see Inform Participants Operation section).
The RejectionType.CircuitBreaker is the rejection reason the managing exchange responds with when a participant submits a spot tender that would exceed a software circuit breaker. This is an uncommon scenario (circuit breaker triggers are set at significantly higher currents than the expected load) and typically short-lived. The participant exchange forwards this response internally for later analysis but does not change its behavior.
The RejectionType.DuplicateTender is the rejection reason the managing exchange responds with when a participant submits the same tender (or tender ID for cancelation) more than once. Similarly, the RejectionType.InvalidTender is the rejection reason the managing exchange responds with when a participant submits a tender (or tender ID for cancelation) with an invalid tender ID or properties (e.g., the tender already expired or targets a non-tradeable instrument). The RejectionReason always includes the tender IDs with both rejection types. A message delivery or processing delay is the most common cause for these rejection types. The participant exchange considers these rejections transient errors. The participant exchange forwards the response internally for later analysis but does not change its behavior.
The RejectionType.ForceMajeure is the rejection reason the managing exchange responds with when a participant submits a market request during a force majeure while the markets are still open. Only the market operator can activate force majeure in a marketplace. This is an uncommon scenario and typically market operator would also close the market. The participant exchange forwards this response internally for later analysis but does not change its behavior.
Additional details on the Rejection Types + Message Notes and Triggers:
|
|
|
Rejection Trigger
|
|
|
|
The participant is suspended or unauthorized from making this call.
|
|
|
|
A participant submits a tender for a market the managing exchange has already closed.
|
|
|
Market permanently closed.
|
A participant submits a tender for a market that the managing exchange has deleted.
|
|
|
Duplicate tender in the submitted tender request
|
A participant submits tenders with the same tender ID in the same request.
|
|
|
The tender was already submitted
|
A participant re-submits an earlier tender.
|
|
|
|
|
|
The tender's status must be 'Pending'
|
A participant submits a tender that is not in the 'Pending' state.
|
|
|
The tender's committed power must be 0
|
A participant submits a tender that has already committed power.
|
|
|
Invalid tender market code
|
A participant submits a tender that references a market that does not exist in the marketplace.
|
|
|
Tender's unit price [unitPrice] is not compliant with the marketplace's financial rules
|
A participant submits a tender with a unit price that does not comply with the marketplace's rules related to price. The tender's unit price is not between
MarketplaceFinancialAspects
.MinUnitPrice
and
MarketplaceFinancialAspects
.MaxUnitPrice
.
|
|
|
The tender does not target a tradeable instrument in the market
|
A participant submits a futures tender with an instrument code that is outside the market's time horizon. The tender's start and end timestamps do not fall within the
MarketTimeAspects
.TimeHorizonStart
and
MarketTimeAspects
.TimeHorizonEnd
range
.
|
|
|
The tender's RateOfDelivery [rateOfDelivery] is not compliant with the market product lot side of [lotSize]
|
A participant submits a futures tender with a rate of delivery that does not comply with the market size granularity. For example, if the market defines a product
MarketProduct
.LotSize
of 0.5 kW, and the participant submits a tender with a rate of delivery of 1.2 kW.
|
|
|
Market [name] maximum load per instrument exceeded
|
A participant submits a futures tender with a rate of delivery that, when combined with the already submitted tenders and contracts for the tender's period, exceeds the market's reserved quota.
|
|
|
The tender's rate of delivery [rateOfDelivery] exceeds the participant's [name] maximum load of [participantConnection.MaximumPower] for connection [participantConnection.Name]
|
A participant submits a futures tender with a rate of delivery that surpasses the
ParticipantConnection
.MaximumPower
.
|
|
|
The tender's rate of delivery [rateOfDelivery] plus the existing tender's power exceeds the participant's [name] maximum load of [participantConnection.MaximumPower] for connection [participantConnection.Name]
|
A participant submits a futures tender with a rate of delivery that, when combined with the already submitted tenders for the tender's period, surpasses the
ParticipantConnection
.MaximumPower
.
|
|
|
Participant's [name] maximum load for connection [participantConnection.Name] exceeded.
|
A participant submits a futures tender with a rate of delivery that, when combined with the already submitted tenders and contracts net position for the tender's period, surpasses the
ParticipantConnection
.MaximumPower
.
|
|
|
The tender's start and end timestamps intersect with the participant's temporal trading restriction.
|
A market operator has imposed a trading restriction on a participant, stating that he is not allowed to trade during a specific period. The same participant submits a tender in violation of the mentioned restriction.
|
|
|
The combined power of the tender and the already accepted power exceeds the participant's power trading restriction.
|
A market operator has imposed a trading restriction on a participant, stating that he is not allowed to trade over or below a specific power limit. The same participant submits a tender in violation of the mentioned restriction.
|
|
|
The tender's unit price exceeds the participant's price trading restriction.
|
A market operator has imposed a trading restriction on a participant, stating that he is not allowed to trade over or below a specific price limit. The same participant submits a tender in violation of the mentioned restriction.
|
|
|
The participant's resilience score [resilienceScore] is lower than its trading restriction [restriction.MinResilienceScore]
|
A market operator has imposed a trading restriction on a participant, stating that he needs to maintain a minimum resilience score to trade in a market. The same participant submits a tender in violation of the mentioned restriction.
|
I hope this helps,
Horia
------------------------------
Horia Pop,
LateralGroup.com, ResilientEnergy.com
------------------------------