// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © TradingView
//@version=6
library("LibraryCOT", overlay = false)
// LibraryCOT Library
// v3, 2024.11.26
// This code was written using the recommendations from the Pine Script™ User Manual's Style guide:
// https://www.tradingview.com/pine-script-docs/writing/style-guide/
//#region ———————————————————— Metric names and valid directions
// +-----------------------------------+------------------------+
// | Legacy (COT) Metric Names | Directions |
// +-----------------------------------+------------------------+
// | Open Interest | No direction |
// | Noncommercial Positions | Long, Short, Spreading |
// | Commercial Positions | Long, Short |
// | Total Reportable Positions | Long, Short |
// | Nonreportable Positions | Long, Short |
// | Traders Total | No direction |
// | Traders Noncommercial | Long, Short, Spreading |
// | Traders Commercial | Long, Short |
// | Traders Total Reportable | Long, Short |
// | Concentration Gross LT 4 TDR | Long, Short |
// | Concentration Gross LT 8 TDR | Long, Short |
// | Concentration Net LT 4 TDR | Long, Short |
// | Concentration Net LT 8 TDR | Long, Short |
// +-----------------------------------+------------------------+
// +-----------------------------------+------------------------+
// | Disaggregated (COT2) Metric Names | Directions |
// +-----------------------------------+------------------------+
// | Open Interest | No direction |
// | Producer Merchant Positions | Long, Short |
// | Swap Positions | Long, Short, Spreading |
// | Managed Money Positions | Long, Short, Spreading |
// | Other Reportable Positions | Long, Short, Spreading |
// | Total Reportable Positions | Long, Short |
// | Nonreportable Positions | Long, Short |
// | Traders Total | No direction |
// | Traders Producer Merchant | Long, Short |
// | Traders Swap | Long, Short, Spreading |
// | Traders Managed Money | Long, Short, Spreading |
// | Traders Other Reportable | Long, Short, Spreading |
// | Traders Total Reportable | Long, Short |
// | Concentration Gross LE 4 TDR | Long, Short |
// | Concentration Gross LE 8 TDR | Long, Short |
// | Concentration Net LE 4 TDR | Long, Short |
// | Concentration Net LE 8 TDR | Long, Short |
// +-----------------------------------+------------------------+
// +-----------------------------------+------------------------+
// | Financial (COT3) Metric Names | Directions |
// +-----------------------------------+------------------------+
// | Open Interest | No direction |
// | Dealer Positions | Long, Short, Spreading |
// | Asset Manager Positions | Long, Short, Spreading |
// | Leveraged Funds Positions | Long, Short, Spreading |
// | Other Reportable Positions | Long, Short, Spreading |
// | Total Reportable Positions | Long, Short |
// | Nonreportable Positions | Long, Short |
// | Traders Total | No direction |
// | Traders Dealer | Long, Short, Spreading |
// | Traders Asset Manager | Long, Short, Spreading |
// | Traders Leveraged Funds | Long, Short, Spreading |
// | Traders Other Reportable | Long, Short, Spreading |
// | Traders Total Reportable | Long, Short |
// | Concentration Gross LE 4 TDR | Long, Short |
// | Concentration Gross LE 8 TDR | Long, Short |
// | Concentration Net LE 4 TDR | Long, Short |
// | Concentration Net LE 8 TDR | Long, Short |
// +-----------------------------------+------------------------+
//#endregion
//#region ———————————————————— Library functions
// @function Checks whether the given string is not empty.
// @param str (string) The string to inspect.
// @returns (bool) `true` if the string is not empty, `false` otherwise.
isNotEmpty(string str) =>
bool result = str != ""
// @function Creates a map of futures symbol root prefixes and their corresponding CFTC Commitment of
// Traders (COT) report codes.
// @returns (map<string, string>) A map of "string" keys representing root prefixes and "string"
// values representing CFTC root codes.
createRootCodeMap() =>
map<string, string> rootCodeMap = map.new<string, string>()
rootCodeMap.put("AMB1", "1450E1")
rootCodeMap.put("AMT1", "1450E4")
rootCodeMap.put("VM" , "1170E8")
rootCodeMap.put("VXM" , "1170E8")
rootCodeMap.put("IBHY", "2520E1")
rootCodeMap.put("IBIG", "2520E2")
rootCodeMap.put("VX" , "1170E1")
rootCodeMap.put("VX10", "117E10")
rootCodeMap.put("VX11", "117E11")
rootCodeMap.put("VX13", "117E13")
rootCodeMap.put("VX14", "117E14")
rootCodeMap.put("VX15", "117E15")
rootCodeMap.put("VX17", "117E17")
rootCodeMap.put("VX18", "117E18")
rootCodeMap.put("VX19", "117E19")
rootCodeMap.put("VX21", "117E21")
rootCodeMap.put("VX22", "117E22")
rootCodeMap.put("VX23", "117E23")
rootCodeMap.put("VX24", "117E24")
rootCodeMap.put("VX26", "117E26")
rootCodeMap.put("VX27", "117E27")
rootCodeMap.put("VX28", "117E28")
rootCodeMap.put("VX30", "117E30")
rootCodeMap.put("VX31", "117E31")
rootCodeMap.put("VX32", "117E32")
rootCodeMap.put("VX34", "117E34")
rootCodeMap.put("VX35", "117E35")
rootCodeMap.put("VX36", "117E36")
rootCodeMap.put("VX37", "117E37")
rootCodeMap.put("VX39", "117E39")
rootCodeMap.put("VX40", "117E40")
rootCodeMap.put("VX41", "117E41")
rootCodeMap.put("VX43", "117E43")
rootCodeMap.put("VX09", "117E09")
rootCodeMap.put("YIA" , "342602")
rootCodeMap.put("YIY" , "343603")
rootCodeMap.put("N1S" , "343604")
rootCodeMap.put("YIT" , "342603")
rootCodeMap.put("TWE" , "020605")
rootCodeMap.put("YIC" , "344606")
rootCodeMap.put("YIE" , "320604")
rootCodeMap.put("25U" , "046603")
rootCodeMap.put("30U" , "046604")
rootCodeMap.put("35U" , "046605")
rootCodeMap.put("40U" , "046606")
rootCodeMap.put("45U" , "046607")
rootCodeMap.put("50U" , "046608")
rootCodeMap.put("55U" , "046609")
rootCodeMap.put("60U" , "046610")
rootCodeMap.put("YID" , "344604")
rootCodeMap.put("YIW" , "344605")
rootCodeMap.put("F1S" , "344615")
rootCodeMap.put("YIB" , "344607")
rootCodeMap.put("BWF" , "00160F")
rootCodeMap.put("AW" , "221602")
rootCodeMap.put("DRS" , "221604")
rootCodeMap.put("CWR" , "00160D")
rootCodeMap.put("ZC" , "002602")
rootCodeMap.put("DFN" , "251605")
rootCodeMap.put("YM" , "124603")
rootCodeMap.put("RX" , "124606")
rootCodeMap.put("SAS" , "005609")
rootCodeMap.put("10Y" , "04360Y")
rootCodeMap.put("2YY" , "04260Y")
rootCodeMap.put("30Y" , "02060Y")
rootCodeMap.put("5YY" , "04460Y")
rootCodeMap.put("MYM" , "124608")
rootCodeMap.put("XC" , "002603")
rootCodeMap.put("XK" , "005603")
rootCodeMap.put("XW" , "001603")
rootCodeMap.put("ZO" , "004603")
rootCodeMap.put("ZR" , "039601")
rootCodeMap.put("ZM" , "026603")
rootCodeMap.put("ZL" , "007601")
rootCodeMap.put("ZS" , "005602")
rootCodeMap.put("ZB" , "020601")
rootCodeMap.put("UNO" , "251609")
rootCodeMap.put("TN" , "043607")
rootCodeMap.put("UB" , "020604")
rootCodeMap.put("UFB" , "251604")
rootCodeMap.put("UFE" , "251606")
rootCodeMap.put("UME" , "251603")
rootCodeMap.put("UFV" , "251607")
rootCodeMap.put("ZW" , "001602")
rootCodeMap.put("ZQ" , "045601")
rootCodeMap.put("ZN" , "043602")
rootCodeMap.put("ZF" , "044601")
rootCodeMap.put("Z3N" , "038601")
rootCodeMap.put("KE" , "001612")
rootCodeMap.put("ZT" , "042601")
rootCodeMap.put("SR1" , "134742")
rootCodeMap.put("SR3" , "134741")
rootCodeMap.put("AQR" , "209748")
rootCodeMap.put("A2R" , "239749")
rootCodeMap.put("ASR" , "13874W")
rootCodeMap.put("D2" , "17564H")
rootCodeMap.put("D2X" , "16S063")
rootCodeMap.put("K1" , "16064C")
rootCodeMap.put("H1" , "16064H")
rootCodeMap.put("K1K" , "16S023")
rootCodeMap.put("H1X" , "16S056")
rootCodeMap.put("ACD" , "432741")
rootCodeMap.put("AJY" , "632741")
rootCodeMap.put("ANE" , "532741")
rootCodeMap.put("6A" , "232741")
rootCodeMap.put("BTC" , "133741")
rootCodeMap.put("BLK" , "063643")
rootCodeMap.put("KW" , "17064C")
rootCodeMap.put("HWX" , "16S061")
rootCodeMap.put("6L" , "102741")
rootCodeMap.put("6B" , "096742")
rootCodeMap.put("6C" , "090741")
rootCodeMap.put("CJY" , "190741")
rootCodeMap.put("CB" , "050642")
rootCodeMap.put("CSC" , "063642")
rootCodeMap.put("K2N" , "16S183")
rootCodeMap.put("K2K" , "16S186")
rootCodeMap.put("K2" , "16164C")
rootCodeMap.put("H2" , "16164H")
rootCodeMap.put("H2X" , "16S042")
rootCodeMap.put("CHP" , "279742")
rootCodeMap.put("K3" , "16364C")
rootCodeMap.put("K3K" , "16364D")
rootCodeMap.put("K3N" , "163K3N")
rootCodeMap.put("H3" , "16364H")
rootCodeMap.put("H3Z" , "16S002")
rootCodeMap.put("H3X" , "16S050")
rootCodeMap.put("GDK" , "052644")
rootCodeMap.put("BOS" , "20074A")
rootCodeMap.put("CHI" , "20074B")
rootCodeMap.put("CUS" , "20074K")
rootCodeMap.put("DEN" , "20074C")
rootCodeMap.put("LAV" , "20074D")
rootCodeMap.put("LAX" , "20074E")
rootCodeMap.put("MIA" , "20074F")
rootCodeMap.put("NYM" , "20074G")
rootCodeMap.put("SDG" , "20074H")
rootCodeMap.put("SFR" , "20074I")
rootCodeMap.put("WDC" , "20074J")
rootCodeMap.put("CZK" , "275741")
rootCodeMap.put("K5" , "16464C")
rootCodeMap.put("H5" , "16464H")
rootCodeMap.put("K5N" , "16S045")
rootCodeMap.put("K5K" , "16S016")
rootCodeMap.put("H5X" , "16S053")
rootCodeMap.put("DY" , "052645")
rootCodeMap.put("M6A" , "232742")
rootCodeMap.put("M6B" , "096746")
rootCodeMap.put("MCD" , "090744")
rootCodeMap.put("M6E" , "099743")
rootCodeMap.put("MSF" , "092744")
rootCodeMap.put("M6J" , "097745")
rootCodeMap.put("M6C" , "090747")
rootCodeMap.put("M6S" , "092748")
rootCodeMap.put("E7" , "099742")
rootCodeMap.put("IPO" , "164741")
rootCodeMap.put("J7" , "097744")
rootCodeMap.put("NIY" , "240745")
rootCodeMap.put("SOX" , "13874Y")
rootCodeMap.put("RSV" , "239744")
rootCodeMap.put("RSG" , "239745")
rootCodeMap.put("RS1" , "239743")
rootCodeMap.put("R2V" , "239746")
rootCodeMap.put("R2G" , "239748")
rootCodeMap.put("RTY" , "239742")
rootCodeMap.put("EMD" , "33874A")
rootCodeMap.put("ESG" , "13874S")
rootCodeMap.put("ES" , "13874A")
rootCodeMap.put("SXT" , "13874Z")
rootCodeMap.put("E3G" , "13874X")
rootCodeMap.put("SXO" , "138743")
rootCodeMap.put("XAR" , "13874R")
rootCodeMap.put("SXB" , "138752")
rootCodeMap.put("SXR" , "138751")
rootCodeMap.put("XAZ" , "13874P")
rootCodeMap.put("XAY" , "138747")
rootCodeMap.put("XAP" , "138748")
rootCodeMap.put("XAE" , "138749")
rootCodeMap.put("XAF" , "13874C")
rootCodeMap.put("XAV" , "13874E")
rootCodeMap.put("XAI" , "13874F")
rootCodeMap.put("SXI" , "138753")
rootCodeMap.put("XAB" , "13874H")
rootCodeMap.put("XAK" , "13874I")
rootCodeMap.put("XAU" , "13874J")
rootCodeMap.put("SMC" , "338742")
rootCodeMap.put("D4X" , "16042I")
rootCodeMap.put("EBR" , "133744")
rootCodeMap.put("ETH" , "146021")
rootCodeMap.put("EAD" , "199741")
rootCodeMap.put("ECD" , "699741")
rootCodeMap.put("RY" , "399741")
rootCodeMap.put("ENK" , "799741")
rootCodeMap.put("ESK" , "899741")
rootCodeMap.put("RF" , "499741")
rootCodeMap.put("6E" , "099741")
rootCodeMap.put("RP" , "299741")
rootCodeMap.put("ESR" , "047745")
rootCodeMap.put("EUS" , "598742")
rootCodeMap.put("ECK" , "275742")
rootCodeMap.put("EPZ" , "277742")
rootCodeMap.put("GF" , "061641")
rootCodeMap.put("HUF" , "274741")
rootCodeMap.put("EHF" , "274743")
rootCodeMap.put("SIR" , "131741")
rootCodeMap.put("MIR" , "131742")
rootCodeMap.put("ISL" , "278741")
rootCodeMap.put("6J" , "097741")
rootCodeMap.put("KRW" , "086741")
rootCodeMap.put("K0" , "16964C")
rootCodeMap.put("H0" , "16964H")
rootCodeMap.put("K0K" , "16S025")
rootCodeMap.put("H0X" , "16S189")
rootCodeMap.put("HE" , "054642")
rootCodeMap.put("LE" , "057642")
rootCodeMap.put("D0X" , "16S039")
rootCodeMap.put("LBR" , "058644")
rootCodeMap.put("TIE" , "134743")
rootCodeMap.put("6M" , "095741")
rootCodeMap.put("MBT" , "133742")
rootCodeMap.put("MNQ" , "209747")
rootCodeMap.put("M2K" , "239747")
rootCodeMap.put("MMC" , "33874B")
rootCodeMap.put("MES" , "13874U")
rootCodeMap.put("MSC" , "338744")
rootCodeMap.put("MET" , "146022")
rootCodeMap.put("DC" , "052641")
rootCodeMap.put("JQ" , "052648")
rootCodeMap.put("KQK" , "17364D")
rootCodeMap.put("HQX" , "16S052")
rootCodeMap.put("BIO" , "209744")
rootCodeMap.put("H2O" , "147641")
rootCodeMap.put("NDA" , "438741")
rootCodeMap.put("NQ" , "209742")
rootCodeMap.put("VLQ" , "117742")
rootCodeMap.put("K4" , "16264C")
rootCodeMap.put("H4" , "16264H")
rootCodeMap.put("H4Z" , "16S003")
rootCodeMap.put("K4N" , "16S181")
rootCodeMap.put("K4K" , "16S018")
rootCodeMap.put("H4X" , "16S041")
rootCodeMap.put("6N" , "112741")
rootCodeMap.put("NKD" , "240741")
rootCodeMap.put("ENY" , "240743")
rootCodeMap.put("GNF" , "052642")
rootCodeMap.put("NOK" , "273741")
rootCodeMap.put("K6" , "16564C")
rootCodeMap.put("H6Z" , "16S168")
rootCodeMap.put("PLN" , "277741")
rootCodeMap.put("PRK" , "054643")
rootCodeMap.put("K7K" , "16S185")
rootCodeMap.put("K7" , "16664C")
rootCodeMap.put("H7X" , "16S059")
rootCodeMap.put("PSF" , "296741")
rootCodeMap.put("PJY" , "396741")
rootCodeMap.put("SON" , "047743")
rootCodeMap.put("RDA" , "239750")
rootCodeMap.put("SDA" , "43874A")
rootCodeMap.put("SDI" , "43874Q")
rootCodeMap.put("TRI" , "13874N")
rootCodeMap.put("GD" , "256741")
rootCodeMap.put("GIE" , "256742")
rootCodeMap.put("KS" , "17464C")
rootCodeMap.put("KSN" , "16S187")
rootCodeMap.put("HSX" , "16S188")
rootCodeMap.put("6Z" , "122741")
rootCodeMap.put("ZAR" , "122742")
rootCodeMap.put("SEK" , "264741")
rootCodeMap.put("6S" , "092741")
rootCodeMap.put("SJY" , "192741")
rootCodeMap.put("BSB" , "157741")
rootCodeMap.put("TPD" , "241740")
rootCodeMap.put("TRL" , "019743")
rootCodeMap.put("IBV" , "130741")
rootCodeMap.put("CPO" , "037021")
rootCodeMap.put("RMB" , "082744")
rootCodeMap.put("TPY" , "243742")
rootCodeMap.put("ALA" , "191698")
rootCodeMap.put("EDP" , "191696")
rootCodeMap.put("AEP" , "191694")
rootCodeMap.put("MJP" , "191695")
rootCodeMap.put("ALI" , "191691")
rootCodeMap.put("AUP" , "191693")
rootCodeMap.put("COB" , "188691")
rootCodeMap.put("HG" , "085692")
rootCodeMap.put("HGS" , "085695")
rootCodeMap.put("QC" , "085693")
rootCodeMap.put("GC" , "088691")
rootCodeMap.put("FSF" , "257651")
rootCodeMap.put("TIO" , "195651")
rootCodeMap.put("PAC" , "195656")
rootCodeMap.put("LTC" , "189692")
rootCodeMap.put("LTH" , "189691")
rootCodeMap.put("MHG" , "085699")
rootCodeMap.put("MGC" , "088695")
rootCodeMap.put("SIL" , "084694")
rootCodeMap.put("QO" , "088692")
rootCodeMap.put("QI" , "084692")
rootCodeMap.put("MOX" , "192656")
rootCodeMap.put("EHR" , "192691")
rootCodeMap.put("SGC" , "088698")
rootCodeMap.put("SGU" , "088697")
rootCodeMap.put("SI" , "084691")
rootCodeMap.put("BUS" , "257652")
rootCodeMap.put("HRC" , "192651")
rootCodeMap.put("HDG" , "192692")
rootCodeMap.put("UX" , "016651")
rootCodeMap.put("BTI" , "133LM2")
rootCodeMap.put("ETI" , "146LM2")
rootCodeMap.put("OIL" , "067LM1")
rootCodeMap.put("BIT" , "133LM1")
rootCodeMap.put("ET" , "146LM1")
rootCodeMap.put("BMC" , "133SG2")
rootCodeMap.put("SDX" , "098SG1")
rootCodeMap.put("TM" , "067SG1")
rootCodeMap.put("SR1" , "134731")
rootCodeMap.put("SR3" , "134730")
rootCodeMap.put("30C" , "203061")
rootCodeMap.put("AS" , "232663")
rootCodeMap.put("YA" , "332661")
rootCodeMap.put("AR" , "432661")
rootCodeMap.put("AWN" , "24478F")
rootCodeMap.put("BTM" , "133732")
rootCodeMap.put("QA" , "232662")
rootCodeMap.put("PC" , "090663")
rootCodeMap.put("GN" , "112662")
rootCodeMap.put("PK" , "273661")
rootCodeMap.put("PS" , "264661")
rootCodeMap.put("KSV" , "090771")
rootCodeMap.put("HY" , "090661")
rootCodeMap.put("CC" , "073732")
rootCodeMap.put("KC" , "083731")
rootCodeMap.put("CT" , "033661")
rootCodeMap.put("VC" , "275663")
rootCodeMap.put("YZ" , "122662")
rootCodeMap.put("EZ" , "275662")
rootCodeMap.put("HR" , "274662")
rootCodeMap.put("OJ" , "040701")
rootCodeMap.put("VU" , "274663")
rootCodeMap.put("IUS" , "224770")
rootCodeMap.put("ILS" , "278661")
rootCodeMap.put("SY" , "296661")
rootCodeMap.put("KSN" , "097771")
rootCodeMap.put("MMW" , "24477M")
rootCodeMap.put("ASN" , "24477G")
rootCodeMap.put("MLE" , "24477F")
rootCodeMap.put("MUN" , "244043")
rootCodeMap.put("MWL" , "244051")
rootCodeMap.put("ASI" , "244061")
rootCodeMap.put("MTO" , "24478L")
rootCodeMap.put("LFG" , "244781")
rootCodeMap.put("MTN" , "24478K")
rootCodeMap.put("MFS" , "244041")
rootCodeMap.put("MVU" , "244786")
rootCodeMap.put("MTL" , "24478J")
rootCodeMap.put("MMC" , "244784")
rootCodeMap.put("MMM" , "24477X")
rootCodeMap.put("LFM" , "24477Z")
rootCodeMap.put("MME" , "244042")
rootCodeMap.put("MML" , "24477J")
rootCodeMap.put("MMN" , "24477R")
rootCodeMap.put("MMR" , "24478H")
rootCodeMap.put("MVT" , "244788")
rootCodeMap.put("LFU" , "244782")
rootCodeMap.put("EU9" , "24477V")
rootCodeMap.put("MVV" , "24478G")
rootCodeMap.put("MIN" , "24477P")
rootCodeMap.put("JPP" , "244771")
rootCodeMap.put("PAC" , "24478B")
rootCodeMap.put("MPA" , "24477U")
rootCodeMap.put("MVS" , "244787")
rootCodeMap.put("LFA" , "24477Y")
rootCodeMap.put("USS" , "244062")
rootCodeMap.put("USC" , "24478E")
rootCodeMap.put("WOW" , "244789")
rootCodeMap.put("MVR" , "244785")
rootCodeMap.put("LFW" , "24404G")
rootCodeMap.put("MWS" , "24477T")
rootCodeMap.put("KAU" , "232666")
rootCodeMap.put("KEO" , "116667")
rootCodeMap.put("KRA" , "099663")
rootCodeMap.put("KGB" , "599663")
rootCodeMap.put("KEP" , "699663")
rootCodeMap.put("KEJ" , "299663")
rootCodeMap.put("KRK" , "399664")
rootCodeMap.put("KRZ" , "499663")
rootCodeMap.put("KOL" , "799662")
rootCodeMap.put("KZY" , "492662")
rootCodeMap.put("KZX" , "112665")
rootCodeMap.put("ZJ" , "112663")
rootCodeMap.put("NT" , "116665")
rootCodeMap.put("KY" , "273662")
rootCodeMap.put("NJ" , "276661")
rootCodeMap.put("FNG" , "223772")
rootCodeMap.put("PLN" , "277661")
rootCodeMap.put("PLE" , "277662")
rootCodeMap.put("HIO" , "084043")
rootCodeMap.put("SB" , "080732")
rootCodeMap.put("SF" , "080737")
rootCodeMap.put("KJ" , "264662")
rootCodeMap.put("SS" , "196661")
rootCodeMap.put("KMF" , "092661")
rootCodeMap.put("TRM" , "019661")
rootCodeMap.put("MP" , "096773")
rootCodeMap.put("ZR" , "122661")
rootCodeMap.put("KX" , "264663")
rootCodeMap.put("DX" , "098662")
rootCodeMap.put("KMP" , "095661")
rootCodeMap.put("AFI" , "86565D")
rootCodeMap.put("BOO" , "86565G")
rootCodeMap.put("FO" , "86565C")
rootCodeMap.put("BEF" , "066A28")
rootCodeMap.put("AE5" , "067A31")
rootCodeMap.put("A7E" , "06665B")
rootCodeMap.put("22" , "066A09")
rootCodeMap.put("A91" , "066A07")
rootCodeMap.put("3NA" , "066A27")
rootCodeMap.put("A9N" , "06665A")
rootCodeMap.put("ANT" , "067A85")
rootCodeMap.put("BKT" , "067A88")
rootCodeMap.put("CY" , "06765N")
rootCodeMap.put("AJ9" , "067A25")
rootCodeMap.put("BZ" , "06765T")
rootCodeMap.put("ADB" , "06765O")
rootCodeMap.put("CGO" , "006NLK")
rootCodeMap.put("GEO" , "006NJZ")
rootCodeMap.put("NGO" , "00665T")
rootCodeMap.put("CU" , "025651")
rootCodeMap.put("A5C" , "022A56")
rootCodeMap.put("MTF" , "024656")
rootCodeMap.put("MFF" , "024658")
rootCodeMap.put("CS4" , "2616AC")
rootCodeMap.put("A8M" , "06665V")
rootCodeMap.put("CBB" , "066A16")
rootCodeMap.put("A8L" , "06665U")
rootCodeMap.put("CGB" , "066A15")
rootCodeMap.put("A8K" , "06665T")
rootCodeMap.put("CPB" , "066A14")
rootCodeMap.put("CL" , "067651")
rootCodeMap.put("26" , "067A37")
rootCodeMap.put("AFY" , "06765M")
rootCodeMap.put("DCB" , "06765G")
rootCodeMap.put("TFU" , "023C06")
rootCodeMap.put("TTF" , "023B98")
rootCodeMap.put("TTG" , "023C08")
rootCodeMap.put("QM" , "067655")
rootCodeMap.put("QU" , "11165M")
rootCodeMap.put("QH" , "022656")
rootCodeMap.put("QG" , "023655")
rootCodeMap.put("EWG" , "111A50")
rootCodeMap.put("EWN" , "03265H")
rootCodeMap.put("AA5" , "022A57")
rootCodeMap.put("AZ1" , "025608")
rootCodeMap.put("Z1B" , "025659")
rootCodeMap.put("AKR" , "02165O")
rootCodeMap.put("UV" , "02165E")
rootCodeMap.put("AGT" , "02265X")
rootCodeMap.put("AET" , "02265P")
rootCodeMap.put("R5F" , "021A70")
rootCodeMap.put("GZ" , "86765C")
rootCodeMap.put("7F" , "022A69")
rootCodeMap.put("AGX" , "02265V")
rootCodeMap.put("A43" , "03265G")
rootCodeMap.put("AKZ" , "03265E")
rootCodeMap.put("UN" , "03265A")
rootCodeMap.put("EN" , "86665A")
rootCodeMap.put("APS" , "066652")
rootCodeMap.put("A32" , "066A06")
rootCodeMap.put("EPN" , "066A22")
rootCodeMap.put("FLJ" , "2616A8")
rootCodeMap.put("TM" , "261654")
rootCodeMap.put("TH" , "261653")
rootCodeMap.put("T2D" , "26165V")
rootCodeMap.put("TL" , "261655")
rootCodeMap.put("EVC" , "021A56")
rootCodeMap.put("AQA" , "022A24")
rootCodeMap.put("AVL" , "022A25")
rootCodeMap.put("A8B" , "111A62")
rootCodeMap.put("AA8" , "111A08")
rootCodeMap.put("AA6" , "022A60")
rootCodeMap.put("AB6" , "022B22")
rootCodeMap.put("BCR" , "111A61")
rootCodeMap.put("CRB" , "111A34")
rootCodeMap.put("GFC" , "86565H")
rootCodeMap.put("ME" , "86465A")
rootCodeMap.put("GCI" , "86565N")
rootCodeMap.put("GCU" , "021A28")
rootCodeMap.put("ALY" , "022A05")
rootCodeMap.put("GBB" , "111A55")
rootCodeMap.put("A1G" , "022A61")
rootCodeMap.put("ABH" , "022657")
rootCodeMap.put("HOB" , "867652")
rootCodeMap.put("NN" , "03565B")
rootCodeMap.put("HH" , "023A55")
rootCodeMap.put("HP" , "023A56")
rootCodeMap.put("NPG" , "03565C")
rootCodeMap.put("JA" , "03265C")
rootCodeMap.put("AJB" , "86665B")
rootCodeMap.put("E6" , "03265F")
rootCodeMap.put("HJC" , "86465D")
rootCodeMap.put("A1M" , "86465K")
rootCodeMap.put("AWJ" , "067A07")
rootCodeMap.put("BL2" , "2616AA")
rootCodeMap.put("JKM" , "86665H")
rootCodeMap.put("NWM" , "023C07")
rootCodeMap.put("AKL" , "022A21")
rootCodeMap.put("AJL" , "11165W")
rootCodeMap.put("AJS" , "86465G")
rootCodeMap.put("MQA" , "022B23")
rootCodeMap.put("FLP" , "26165T")
rootCodeMap.put("AYV" , "067A16")
rootCodeMap.put("CMS" , "407653")
rootCodeMap.put("MT2" , "407651")
rootCodeMap.put("MEF" , "021A62")
rootCodeMap.put("R5O" , "021A66")
rootCodeMap.put("M1B" , "022B21")
rootCodeMap.put("MHO" , "022B24")
rootCodeMap.put("MRB" , "111660")
rootCodeMap.put("S5O" , "021A72")
rootCodeMap.put("MAF" , "021A61")
rootCodeMap.put("MCL" , "067A55")
rootCodeMap.put("MAA" , "066A26")
rootCodeMap.put("MAE" , "066A21")
rootCodeMap.put("MAS" , "066A20")
rootCodeMap.put("MBC" , "0676A4")
rootCodeMap.put("A0D" , "021A17")
rootCodeMap.put("MUD" , "022A99")
rootCodeMap.put("R5M" , "021A68")
rootCodeMap.put("RBM" , "021A80")
rootCodeMap.put("MJC" , "86465P")
rootCodeMap.put("MEE" , "86665G")
rootCodeMap.put("MNC" , "03265J")
rootCodeMap.put("MPS" , "066A25")
rootCodeMap.put("MEO" , "111A47")
rootCodeMap.put("MEB" , "111A52")
rootCodeMap.put("MJN" , "86665E")
rootCodeMap.put("E6M" , "86665F")
rootCodeMap.put("MXB" , "111A54")
rootCodeMap.put("MXR" , "111A53")
rootCodeMap.put("MTS" , "021A35")
rootCodeMap.put("S5M" , "021A65")
rootCodeMap.put("SBM" , "021A77")
rootCodeMap.put("5L" , "021A20")
rootCodeMap.put("A0F" , "021A19")
rootCodeMap.put("MSG" , "022B09")
rootCodeMap.put("A8C" , "06665Y")
rootCodeMap.put("A8O" , "06665W")
rootCodeMap.put("51" , "066A05")
rootCodeMap.put("PMF" , "066A30")
rootCodeMap.put("AR0" , "06665X")
rootCodeMap.put("A8J" , "06665Z")
rootCodeMap.put("MBR" , "405652")
rootCodeMap.put("MBL" , "066A23")
rootCodeMap.put("A81" , "066A10")
rootCodeMap.put("MBE" , "405654")
rootCodeMap.put("AC0" , "06665P")
rootCodeMap.put("B0" , "06665O")
rootCodeMap.put("A7Q" , "06665R")
rootCodeMap.put("A8I" , "06665S")
rootCodeMap.put("AD0" , "06665Q")
rootCodeMap.put("NOO" , "86665C")
rootCodeMap.put("NG" , "023651")
rootCodeMap.put("JCC" , "023C04")
rootCodeMap.put("AEZ" , "025652")
rootCodeMap.put("A7Y" , "022A66")
rootCodeMap.put("HO" , "022651")
rootCodeMap.put("JET" , "86465S")
rootCodeMap.put("JTB" , "86465T")
rootCodeMap.put("MPX" , "02265A")
rootCodeMap.put("MM" , "02165B")
rootCodeMap.put("AHL" , "86765A")
rootCodeMap.put("ULB" , "022A97")
rootCodeMap.put("PA" , "075651")
rootCodeMap.put("PGG" , "406651")
rootCodeMap.put("AL1" , "064A58")
rootCodeMap.put("JDL" , "064659")
rootCodeMap.put("PL" , "076651")
rootCodeMap.put("A3G" , "111A02")
rootCodeMap.put("A1R" , "06665G")
rootCodeMap.put("1S" , "06665H")
rootCodeMap.put("RLX" , "11165K")
rootCodeMap.put("ZXY" , "967652")
rootCodeMap.put("1E" , "96765F")
rootCodeMap.put("A1D" , "111A09")
rootCodeMap.put("RLX" , "11165J")
rootCodeMap.put("RBB" , "111A41")
rootCodeMap.put("EXR" , "111A45")
rootCodeMap.put("ARY" , "86265C")
rootCodeMap.put("RB" , "111659")
rootCodeMap.put("ABS" , "02165M")
rootCodeMap.put("SD" , "02165J")
rootCodeMap.put("S5F" , "021A71")
rootCodeMap.put("S5B" , "021A82")
rootCodeMap.put("S53" , "021A73")
rootCodeMap.put("SR5" , "021A83")
rootCodeMap.put("UA" , "02165G")
rootCodeMap.put("SE" , "02165K")
rootCodeMap.put("SF3" , "86565P")
rootCodeMap.put("SGB" , "02265J")
rootCodeMap.put("AVU" , "022A22")
rootCodeMap.put("AGA" , "02265T")
rootCodeMap.put("RKA" , "86465C")
rootCodeMap.put("D1N" , "111A46")
rootCodeMap.put("N1B" , "111A11")
rootCodeMap.put("A1P" , "111A12")
rootCodeMap.put("ATP" , "022A32")
rootCodeMap.put("A1L" , "022A62")
rootCodeMap.put("LT" , "022A13")
rootCodeMap.put("H5F" , "021A76")
rootCodeMap.put("A42" , "067A45")
rootCodeMap.put("CSX" , "06765A")
rootCodeMap.put("HTT" , "0676A5")
rootCodeMap.put("AFF" , "067A69")
rootCodeMap.put("WTT" , "067A71")
rootCodeMap.put("BK" , "06765L")
rootCodeMap.put("WTL" , "067A86")
rootCodeMap.put("AFH" , "067A24")
rootCodeMap.put("QMW" , "001626")
rootCodeMap
// @function Retrieves a pre-initialized map of futures symbol root prefixes and their corresponding
// CFTC Commitment of Traders (COT) report codes.
// @returns (map<string, string>) A map of "string" keys containing root prefixes and "string"
// values containing CFTC root codes.
getRootCodeMap() =>
var map<string, string> rootCodeMap = createRootCodeMap()
rootCodeMap
// @function Retrieves the CFTC code corresponding to a futures symbol's root prefix.
// @param root (string) The root prefix of the futures symbol, e.g. "ZC" for "ZC1!" or "ZCU2021".
// @returns (string) The <CFTCCode> part of a COT ticker ID corresponding to the `root`, or an empty
// string if no CFTC code exists for the `root`.
rootToCFTCCode(string root) =>
string code = getRootCodeMap().get(root)
na(code) ? "" : code
// @function Retrieves the CFTC code corresponding to a specified currency.
// @param curr (string) The currency code, e.g., "USD" for US Dollar.
// @returns (string) The <CFTCCode> part of a COT ticker ID corresponding to the `currency`, or an
// empty string if no CFTC code exists for the `currency`.
currencyToCFTCCode(string currency) =>
string code = switch currency
"BTC" => "133741"
"USD" => "098662"
"EUR" => "099741"
"JPY" => "097741"
"MXN" => "095741"
"CHF" => "092741"
"RUB" => "089741"
"CAD" => "090741"
"NZD" => "112741"
"GBP" => "096742"
"BRL" => "102741"
"ZAR" => "122741"
"AUD" => "232741"
"ETH" => "146021"
=> ""
code
// @function Returns the part of the COT ticker ID that specifies whether the report includes options
// data.
// @param includeOptions (bool) `true` if the symbol should include options, `false` otherwise.
// @returns (string) The <includeOptions> part of a COT ticker ID: "FO" for tickers that include
// options and "F" for tickers that do not.
optionsToTicker(bool includeOptions) =>
includeOptions ? "FO" : "F"
// @function Constructs a "string" representing the metric name and direction parts of a COT ticker ID.
// @param metricName (string) One of the valid metric names listed in the within the library's documentation
// and source code. If the argument is not a valid metric name, it causes a runtime error.
// @param metricDirection (string) Metric direction. Possible values are: "Long", "Short", "Spreading", and
// "No direction". If the argument is not a valid direction for the metric, it causes a
// runtime error.
// @returns (string) The <metricCode><metricDirection> portion of a COT ticker ID, e.g., "OI" for
// "Open Interest" and "No direction", or "TC_L" for "Traders Commercial" and "Long".
metricNameAndDirectionToTicker(string metricName, string metricDirection) =>
string metricCode = switch metricName
"Asset Manager Positions" => "AMP"
"Commercial Positions" => "CP"
"Concentration Gross LE 4 TDR" => "CON_GROSS_LE_4"
"Concentration Gross LE 8 TDR" => "CON_GROSS_LE_8"
"Concentration Gross LT 4 TDR" => "CON_GROSS_LT_4"
"Concentration Gross LT 8 TDR" => "CON_GROSS_LT_8"
"Concentration Net LE 4 TDR" => "CON_NET_LE_4"
"Concentration Net LE 8 TDR" => "CON_NET_LE_8"
"Concentration Net LT 4 TDR" => "CON_NET_LT_4"
"Concentration Net LT 8 TDR" => "CON_NET_LT_8"
"Dealer Positions" => "DP"
"Leveraged Funds Positions" => "LMP"
"Managed Money Positions" => "MMP"
"Noncommercial Positions" => "NCP"
"Nonreportable Positions" => "NRP"
"Open Interest" => "OI"
"Other Reportable Positions" => "ORP"
"Producer Merchant Positions" => "PMR"
"Swap Positions" => "SP"
"Total Reportable Positions" => "TRP"
"Traders Asset Manager" => "TAM"
"Traders Commercial" => "TC"
"Traders Dealer" => "TD"
"Traders Leveraged Funds" => "TLM"
"Traders Managed Money" => "TMM"
"Traders Noncommercial" => "TNC"
"Traders Other Reportable" => "TOR"
"Traders Producer Merchant" => "TPM"
"Traders Swap" => "TS"
"Traders Total" => "TT"
"Traders Total Reportable" => "TTR"
=> runtime.error(
str.format(
"Invalid metric name: {1}{0}{1}. See the library{1}s documentation or source code for all valid
metric names.", metricName, "'"
)
), na
string directionCode = switch metricDirection
"Long" => "_L"
"Short" => "_S"
"Spreading" => "_SPREAD"
"No direction" => ""
=> runtime.error(
str.format(
"{1}{0}{1} is not a valid `metricDirection` argument. Possible values:
{1}Long{1}, {1}Short{1}, {1}Spreading{1}, {1}No direction{1}", metricDirection, "'"
)
), na
if metricDirection == "No direction"
if metricName != "Open Interest" and metricName != "Traders Total"
runtime.error(
str.format(
"{2}{0}{2} does not apply to the {2}{1}{2} metric.", metricDirection, metricName, "'"
)
)
else if metricDirection == "Spreading"
isIncorrect = switch metricName
"Commercial Positions" => true
"Total Reportable Positions" => true
"Nonreportable Positions" => true
"Traders Commercial" => true
"Traders Total Reportable" => true
"Concentration Gross LT 4 TDR" => true
"Concentration Gross LT 8 TDR" => true
"Concentration Net LT 4 TDR" => true
"Concentration Net LT 8 TDR" => true
"Concentration Gross LE 4 TDR" => true
"Concentration Gross LE 8 TDR" => true
"Concentration Net LE 4 TDR" => true
"Concentration Net LE 8 TDR" => true
"Producer Merchant Positions" => true
"Traders Producer Merchant" => true
=> false
if isIncorrect
runtime.error(
str.format(
"The {2}{0}{2} direction does not apply to the {2}{1}{2} metric.",
metricDirection, metricName, "'"
)
)
else if metricName == "Open Interest" or metricName == "Traders Total"
runtime.error(
str.format(
"The {2}{0}{2} direction does not apply to the {2}{1}{2} metric.",
metricDirection, metricName, "'"
)
)
metricCode + directionCode
// @function Converts a specified metric type into a required COT ticker ID component.
// See the "Old and Other Futures" section of the CFTC's Explanatory Notes for details on
// types.
// @param metricType (string) The metric type. Possible values are: "All", "Old", "Other".
// @returns (string) The <metricType> part of a COT ticker ID.
typeToTicker(string metricType) =>
string result = switch metricType
"All" => ""
"Old" => "_OLD"
"Other" => "_OTHER"
=> runtime.error(
str.format(
"{1}{0}{1} is not a valid `metricType` argument. Possible values: {1}All{1}, {1}Old{1}, {1}Other{1}",
metricType, "'"
)
), na
// @function Produces a "string" containing the chart symbol's root prefix or currency information, or
// the corresponding CFTC Commitment of Traders (COT) report code, depending on the specified
// `mode` and `convertToCOT` value.
// @param mode (string) Specifies the information the function extracts from a symbol. Possible modes are:
// - "Root":
// The function extracts the futures symbol's root prefix information
// (e.g., "ES" for "ESH2020").
// - "Base currency":
// The function extracts the first currency from a currency pair
// (e.g., "EUR" for "EURUSD").
// - "Currency":
// The function extracts the currency of the symbol's quoted values
// (e.g., "JPY" for "TSE:9984" or "USDJPY").
// - "Auto":
// The function tries the first three modes (Root -> Base currency -> Currency) until
// it finds a match.
// If the specified mode is not available for the symbol, it causes a runtime error.
// @param convertToCOT (bool) If `true`, the function attempts to retrieve the CFTC code corresponding to the
// extracted root prefix, base currency, or quote currency, raising a runtime error if no code
// is available. Otherwise, it returns the root or currency information directly.
// @returns (string) The <CFTCCode> part of a COT ticker ID if `convertToCOT` is `true`. Otherwise, the
// symbol's root or currency information.
export convertRootToCOTCode(string mode, bool convertToCOT = true) =>
bool hasRoot = syminfo.root != syminfo.ticker
string root = rootToCFTCCode(syminfo.root)
string baseCurrency = currencyToCFTCCode(syminfo.basecurrency)
string mainCurrency = currencyToCFTCCode(syminfo.currency)
string result = switch mode
"Auto" =>
switch
hasRoot and isNotEmpty(root) => convertToCOT ? root : syminfo.root
isNotEmpty(baseCurrency) => convertToCOT ? baseCurrency : syminfo.basecurrency
isNotEmpty(mainCurrency) => convertToCOT ? mainCurrency : syminfo.currency
=> ""
"Root" => convertToCOT ? root : syminfo.root
"Base currency" => convertToCOT ? baseCurrency : syminfo.basecurrency
"Currency" => convertToCOT ? mainCurrency : syminfo.currency
=> runtime.error(
str.format(
"{1}{0}{1} is not a valid `mode` argument. Possible values:
{1}Root{1}, {1}Base currency{1}, {1}Currency{1}, {1}Auto{1}", mode, "'"
)
), ""
if result == ""
runtime.error(
str.format(
"No {0}{1} found for the current symbol.",
str.replace(str.lower(mode), "auto", "root or currency"), convertToCOT ? " CFTC code" : ""
)
)
result
// @function Creates a valid TradingView ticker ID for a CFTC Commitment of Traders (COT) symbol with
// specified parameters.
// @param COTType (string) Specifies the report type the ticker represents. Possible values are:
// "Legacy", "Disaggregated", "Financial".
// @param CFTCCode (string) The CFTC code for the asset. For example, wheat futures (root "ZW") have the
// code "001602". Use the library's `convertRootToCOTCode()` function to get a valid code for
// the chart symbol's root, base currency, or main currency.
// @param includeOptions (bool) If `true`, the COT symbol includes options information. Otherwise, it does not.
// @param metricName (string) One of the valid metric names listed in the library's documentation and source code.
// @param metricDirection (string) Metric direction. Possible values are: "Long", "Short", "Spreading", and
// "No direction". Consult this library's documentation or code to see which direction values
// apply to the specified metric.
// @param metricType (string) The metric type. Possible values are: "All", "Old", "Other".
// @returns (string) A COT ticker identifier, which `request.security()` can use to request
// Commitment of Traders data.
export COTTickerid(
string COTType, string CFTCCode, bool includeOptions, string metricName, string metricDirection, string metricType
) =>
string typeCode = switch COTType
"Legacy" => ""
"Disaggregated" => "2"
"Financial" => "3"
=> runtime.error(
str.format(
"{1}{0}{1} is not a valid `COTType` argument. Possible values:
{1}Legacy{1}, {1}Disaggregated{1}, {1}Financial{1}",
COTType, "'"
)
), na
bool invalidType = if COTType == "Legacy"
switch metricName
"Open Interest" => false
"Noncommercial Positions" => false
"Commercial Positions" => false
"Total Reportable Positions" => false
"Nonreportable Positions" => false
"Traders Total" => false
"Traders Noncommercial" => false
"Traders Commercial" => false
"Traders Total Reportable" => false
"Concentration Gross LT 4 TDR" => false
"Concentration Gross LT 8 TDR" => false
"Concentration Net LT 4 TDR" => false
"Concentration Net LT 8 TDR" => false
=> true
else if COTType == "Disaggregated"
switch metricName
"Open Interest" => false
"Producer Merchant Positions" => false
"Swap Positions" => false
"Managed Money Positions" => false
"Other Reportable Positions" => false
"Total Reportable Positions" => false
"Nonreportable Positions" => false
"Traders Total" => false
"Traders Producer Merchant" => false
"Traders Swap" => false
"Traders Managed Money" => false
"Traders Other Reportable" => false
"Traders Total Reportable" => false
"Concentration Gross LE 4 TDR" => false
"Concentration Gross LE 8 TDR" => false
"Concentration Net LE 4 TDR" => false
"Concentration Net LE 8 TDR" => false
=> true
else if COTType == "Financial"
switch metricName
"Open Interest" => false
"Dealer Positions" => false
"Asset Manager Positions" => false
"Leveraged Funds Positions" => false
"Other Reportable Positions" => false
"Total Reportable Positions" => false
"Nonreportable Positions" => false
"Traders Total" => false
"Traders Dealer" => false
"Traders Asset Manager" => false
"Traders Leveraged Funds" => false
"Traders Other Reportable" => false
"Traders Total Reportable" => false
"Concentration Gross LE 4 TDR" => false
"Concentration Gross LE 8 TDR" => false
"Concentration Net LE 4 TDR" => false
"Concentration Net LE 8 TDR" => false
=> true
if invalidType
runtime.error(
str.format(
"{2}{0}{2} is not a valid {1} COT metric. See the library{2}s documentation or code for all valid {1}
metric names.", metricName, COTType, "'"
)
)
string result = str.format(
"COT{0}:{1}_{2}_{3}{4}", typeCode, CFTCCode, optionsToTicker(includeOptions),
metricNameAndDirectionToTicker(metricName, metricDirection), typeToTicker(metricType)
)
// @function Requests CFTC Commitment of Traders (COT) data with specified parameters.
// Calls to this function count toward a script's `request.*()` call limit.
// @param COTType (string) The type of report to request. Possible values are:
// "Legacy", "Disaggregated", "Financial".
// @param CFTCCode (string) The CFTC code for the asset. For example, wheat futures (root "ZW") have the
// code "001602". Use the library's `convertRootToCOTCode()` function to get a valid code for
// the chart symbol's root, base currency, or main currency.
// @param includeOptions (bool) If `true`, the COT symbol includes options information. Otherwise, it does not.
// @param metricName (string) One of the valid metric names listed in the library's documentation and source code.
// @param metricDirection (string) Metric direction. Possible values are: "Long", "Short", "Spreading", and
// "No direction". Consult the library's documentation or code to see which direction values
// apply to the specified metric.
// @param metricType (string) The metric type. Possible values are: "All", "Old", "Other".
// @returns (float) The specified Commitment of Traders data series. If no data is available,
// raises a runtime error.
export requestCommitmentOfTraders(
string COTType, string CFTCCode, bool includeOptions, string metricName, string metricDirection, string metricType
) =>
string t = COTTickerid(COTType, CFTCCode, includeOptions, metricName, metricDirection, metricType)
string tf = timeframe.isdwm ? timeframe.period : "1D"
float data = request.security(t, tf, close, ignore_invalid_symbol = true)
if ta.cum(nz(data)) == 0 and barstate.islastconfirmedhistory
runtime.error(
"The requested COT data is unavailable. Please ensure the report type, CFTC code, and additional
settings represent a valid metric request."
)
data
//#endregion
// ————— Example code
float COTdataseries = requestCommitmentOfTraders(
COTType = "Legacy",
CFTCCode = convertRootToCOTCode("Auto"),
includeOptions = false,
metricName = "Open Interest",
metricDirection = "No direction",
metricType = "All"
)
plot(COTdataseries, style = plot.style_stepline_diamond)
Show all 1,083 lines