ArtsAutosBooksBusinessEducationEntertainmentFamilyFashionFoodGamesGenderHealthHolidaysHomeHubPagesPersonal FinancePetsPoliticsReligionSportsTechnologyTravel

Fetching CME Settlement Prices with Python

Updated on July 25, 2012

Introduction

The Chicago Mercantile Exchange provides a nice interface for accessing futures settlements over FTP. While any production trading house will and should be able to rely on settlements over their direct price feed, accidents do happen and it is relatively easy to use the following script to set up a sanity check (and help avoid those 4am frantic phone calls from traders). The script below is written entirely in the Python programming language and has zero dependencies on outside libraries. As implemented, the script will produce settlements for agricultural products, but by changing the group name in the "if __main__" section, one can get NYMEX products and more. Contact me if you run into any issues.

Python Script

import sys, string, urllib

GROUPS = dict([('ags','ftp://ftp.cmegroup.com/pub/settle/stlags'),
               ('rates','ftp://ftp.cmegroup.com/pub/settle/stlint'),
               ('fx','ftp://ftp.cmegroup.com/pub/settle/stlcur'),
               ('nymex','ftp://ftp.cmegroup.com/pub/settle/stlnymex'),
               ('comex','ftp://ftp.cmegroup.com/settle/stlcomex'),
               ('clearport','ftp://ftp.cmegroup.com/settle/stlcpc')])

# month codes
MONTHDICT = dict([(i+1, 'FGHJKMNQUVXZ'[i]) for i in range(12)])
MONTHDICT.update(dict([('FGHJKMNQUVXZ'[i], i+1) for i in range(12)]))
MONTH_NAMES = 'JAN FEB MAR APR MAY JUN JLY AUG SEP OCT NOV DEC'.split()
MONTHDICT.update(dict(zip(MONTH_NAMES, 'F G H J K M N Q U V X Z'.split())))

def month_code(month):
    return MONTHDICT[month]

def join_words(words, sep):
    """my own simple version of string.join; never deprecated"""
    result = ''
    for word in words[:-1]:
        result += word + sep
    return result + words[-1]

def remove_word(sentence, word, separator):
    return join_words(sentence.split(word), separator).strip()

def Settlements(grp):
    path = GROUPS[grp]
    u = urllib.urlopen(path)
    lines = u.readlines()
    print lines[0].strip()
    u.close()
    RES = {}
    key = None
    for l in lines:
        if len(l.strip()) == 0: continue
        tokens = [t for t in l.split() if len(t.strip()) > 0]
        if tokens[0] == 'TOTAL': continue
        if len(tokens) > 5 and tokens[1] == tokens[2] == tokens[3] \
           == tokens[4] == '----': continue
        try: int(tokens[0]); continue
        except: pass
        if tokens[-1] in ['CALL', 'PUT', '***']: continue
        if tokens[1] == 'SYNTH': continue
        if tokens[-1].lower() in ['future', 'futures', 'swap', 'swp']:
            symbol = tokens[0]
            if tokens[1] == 'Mini-sized': tokens[1] = 'Mini'
            key = (symbol, string.join(tokens[1:], ' ').upper().strip())
            RES[key] = []
            if symbol == 'ED':
                count = 24
            else: count = 3
            continue
        if key != None:
            x = dict(zip('EXP OPEN HI LO LAST SETT CHNG'.split(), tokens[:7]))
            try: x['EXP'] = month_code(x['EXP'][:3]) + x['EXP'][-1]
            except:
                key = None
                continue
            RES[key].append(x)
            count -= 1
            if count == 0: key = None
            continue
    return RES

def DisplaySettlements(grp):
    result = Settlements(grp)
    keys = result.keys()
    keys.sort()
    output = []
    for (symbol, description) in keys:
        if len(result[(symbol, description)]) == 0: continue
        if description == 'MINNEAPOLIS HARD RED SPRING WHEAT FUTURES':
            output.append('MN SPRING WHEAT FUTURES')
        elif description == 'MINNEAPOLIS SOFT RED WINTER WHEAT INDEX FUTURES':
            output.append('MN WINTER WHEAT IDX FUTURES')
        elif description == 'KANSAS CITY WHEAT FUTURES':
            output.append('KC WHEAT FUTURES')
        else:
            d = remove_word(description, 'CME', '')
            output.append(d)
        for d in result[(symbol, description)]:
            line = string.join(['     ', (symbol + d['EXP']).ljust(10),
                                d['SETT'].ljust(8), d['CHNG'].ljust(8)])
            output.append(line)
    return output

if __name__ == '__main__':

    op = DisplaySettlements('ags')
    
    print string.join(op, '\n')

Sample Output for Agricultural Products

taw9@taw9-main ~/pylib $ python mercsettles.py 
FINAL PRE-CLEARING PRICES AS OF 07/24/12 06:00 PM (CST)
ETHANOL FUTURES
      ACFQ2      2.596    -.055   
      ACFU2      2.559    -.050   
      ACFV2      2.520    -.040   
DOW JONES UBS COMMODITY INDEX EXCESS RETURN FUTURE
      AWU2       142.2    -1.3    
SOYBEAN OIL FUTURES
      BOQ2       51.58    -2.17   
      BOU2       51.77    -2.19   
      BOV2       51.96    -2.20   
BLACK SEA WHEAT FUTURES
      BSWU2      300.0    -8.0    
CORN FUTURES
      CU2        790'0    -24'0   
      CZ2        778'2    -7'2    
      CH3        771'4    -5'0    
CASH SETTLED BUTTER FUTURES
      CBN2       154.250  -.600   
      CBU2       166.750  UNCH    
      CBX2       167.000  UNCH    
US DOLLAR DENOMINATED CRUDE PALM OIL FUTURE
      CPOV2      964.75   UNCH    
CASH SETTLED CHEESE FUTURE
      CSCN2      1.687    +.005   
      CSCQ2      1.766    -.009   
      CSCU2      1.870    -.025   
SOYBEAN-CORN INTER-COMMODITY SYNTHETIC FUTURE
      CSIQ2      2.017    -.048   
      CSIU2      2.020    -.004   
      CSIV2      2.017    -.048   
MILK FUTURES
      DAN2       16.68    +.01    
      DAQ2       17.71    -.11    
      DAU2       18.91    -.21    
CLASS IV MILK FUTURES
      DKU2       16.41    -.29    
DRY WHEY FUTURES
      DYN2       49.9750  -.0750  
      DYQ2       53.5000  -.5000  
      DYU2       57.0000  -.5000  
FEEDER CATTLE FUTURES
      FCQ2       137.675  +2.025  
      FCU2       140.350  +2.625  
      FCV2       142.225  +2.450  
BMD CRUDE PALM OIL FUTURE
      FCPQ2      2898     -64     
      FCPU2      2912     -64     
      FCPV2      2926     -64     
KC WHEAT FUTURES
      KEFU2      880'4    -33'4   
      KEFZ2      898'0    -31'4   
      KEFH3      902'0    -32'4   
BMD-KUALA LUMPAR INDEX FUTURE
      KLIN2      1629.00  -5.00   
      KLIQ2      1630.00  -4.50   
      KLIU2      1628.50  -4.00   
LUMBER FUTURES
      LBU2       293.70   -1.20   
      LBX2       287.60   -1.30   
      LBF3       293.60   UNCH    
LIVE CATTLE FUTURES
      LCQ2       118.800  +.200   
      LCV2       123.325  -.175   
      LCZ2       126.400  -.175   
LEAN HOG FUTURES
      LHQ2       92.925   -.400   
      LHV2       78.025   -.825   
      LHZ2       75.600   -.450   
MN SPRING WHEAT FUTURES
      MWEU2      968'0    -37'4   
      MWEZ2      968'4    -36'4   
      MWEH3      973'6    -33'6   
NON-FAT DRY MILK FUTURES
      NFV2       136.500  UNCH    
      NFX2       139.500  +1.000  
      NFZ2       139.000  +1.500  
OATS FUTURES
      OU2        362'4    -18'0   
      OZ2        365'4    -16'6   
      OH3        371'0    -15'6   
ROUGH RICE FUTURES
      RRFU2      15.180   -.270   
      RRFX2      15.450   -.265   
      RRFF3      15.725   -.265   
SOYBEAN FUTURES
      SQ2        1649'2   -49'2   
      SU2        1595'4   -52'2   
      SX2        1569'4   -52'6   
SOYBEAN MEAL FUTURES
      SMQ2       509.8    -13.2   
      SMU2       492.3    -16.0   
      SMV2       477.4    -14.8   
WHEAT FUTURES
      WU2        878'6    -34'0   
      WZ2        888'2    -30'6   
      WH3        885'2    -24'6   
MINI CORN FUTURES
      YCU2       790'0    -24'0   
      YCZ2       778'2    -7'2    
      YCH3       771'4    -5'0    
MINI SOYBEAN FUTURES
      YKQ2       1649'2   -49'2   
      YKU2       1595'4   -52'2   
      YKX2       1569'4   -52'6   
MINI WHEAT FUTURES
      YWU2       878'6    -34'0   
      YWZ2       888'2    -30'6   
      YWH3       885'2    -24'6   

Comments

    0 of 8192 characters used
    Post Comment

    • profile image

      adel 5 years ago

      merci