Hello, wanted to start a thread about the best way to go about getting the ticker for a current contract month. I searched the forum, and didn’t find any prior discussions.
So it seems placing an order requires the full contract ticker name, and it doesn’t allow continuous tickers like ‘@MES’. Question, is it possible to place an order using a contract ID instead of ticker?
Right now to get the full ticker name, I have these calls:
The /suggest operation will return the best maturity first, so the zeroth position is usually the contract to choose. MES runs H, M, U, and Z expiration months, followed by the last digit of the current year (so for the contract expiring in June 2022, MESM2). Here’s a list of the CME group’s month codes. It should be noted that you can request charts for continuous tickers such as @MES, you just can’t trade them because they don’t refer to a specific maturity.
Is it possible for you to tell me which date the /suggest zeroth position for MES changed from MESH2 (March 22) to MESM2 (June 22), just recently?
This would give me a more complete understanding of how to build code around using /suggest for determining the current month maturity.
For example, for MES, these were official published dates from CME:
Roll date: 3/10/22
Expiration: 3/18/22
Majority of volume moved to the June contract on 3/14 - 3/15
What date did /suggest zeroth position change to June? Is it based on official roll date, expiration, volume, or something else calculated by Tradovate?
Contract march contract expired last friday. Most people stop using the expiring contract a week before. So… the “roll” started about: march 10,11th.
Unfortunately… tradovate doesn’t roll the frontmonth in my experience… so you’ll have to stop trading the contract early if you want avoid low liquidity.
Consider this javascript which I used
//from the maturities.. find the 'isFront=true'.. then find the contract that equals that maturity
const maturity = maturities.find(function({ isFront, expirationDate }) {
const expiry = new Date(expirationDate)
const now = new Date()
//https://stackoverflow.com/questions/3224834/get-difference-between-2-dates-in-javascript
const _MS_PER_DAY = 1000 * 60 * 60 * 24;
const dateDiffInDays = Math.floor((expiry - now) / _MS_PER_DAY)
//Rollover is 8 days before expiry but..apparently isFront isn't accurrate near rollover - tradovate has value as true through expiration
//and I don't want to be trading in the final minutes of a contract about to expire
//expires every 3 months.. so 31 days *3 + 8.. lazy math = 100 days
return( (isFront && dateDiffInDays > 7) || (!isFront && dateDiffInDays<100 ) )
log.verbose(`maturity Found:${JSON.stringify(maturity,0,4)}`)
}
@EOD_Trader thank you for describing your experience with isFront, and it is what I was worried about.
I think I’ll get all the maturity dates using contractMaturity/items, and then select the contract where the difference between now and expirationDate is the smallest, but more than a few days. Sounds like a similar approach to yours.
As far as I know, contractSuggest returns a sorted list of active contracts by maturity, so the contract at index 0 will always be the front month contract (someone please correct me if I’m wrong).
I recently implemented a linear search that finds the first of those contracts from contractMaturityItems with over 14 days before expiration. Very similar to what @EOD_Trader has, but simpler.
Since I have previously shared my implementation of contractSuggest, this is a continuation where contract is the array of contracts that contractSuggest returns. You would also want to return more than one result, which I had done in that example.
let id = null;
// Roll from front to back month contract 14 days before expiration
for (let i in contract) {
let expiration = await tvGet("/contractMaturity/item", { id: contract[i].contractMaturityId });
let expirationDays = Math.floor((new Date(expiration.expirationDate) - new Date()) / 86400000);
if (expirationDays > 14) {
id = i;
break;
}
}
contractId = contract[id].id;
Like the previous example I posted, it uses @Alexander’s helper function, tvGet. Since you would only be using the front month or back month contract, the loop will not go beyond the second result to set the expiration cycle.