def get_cot(stem, cot_type='F'): """Get the cot data and cache it (Refresh it if file is older than 7 days). COT Types can be: -- F: Futures Only -- FO: Futures And Options -- F_L: Futures Only Legacy -- FO_L Futures And Options Only :param stem: str - Market stem (customized) :param cot_type: String COT Type :return: Dataframe with COT data """ log = logging.getLogger(__name__) # COT from CFTC Quandl or ICE log.debug('Get {} COT data for: {}'.format(cot_types[cot_type], stem)) path = os.path.join(c.cfg['default']['data'], 'COT', cot_types[cot_type], '{}.csv'.format(stem)) if oci.get(stem, 'Exchange') == 'ICE': if cot_type == 'F_L' or cot_type == 'FO_L': raise Exception( 'Legacy data for COT {} is not supported'.format(stem)) else: if os.path.exists(path): # Read Data from csv file cot = pd.read_csv(path, index_col=0, parse_dates=True) else: raise Exception('File {} is not found'.format(path)) else: # Check if file exists or is not too old if os.path.exists(path) \ and dt.datetime.today() - dt.timedelta(days=2) < dt.datetime.fromtimestamp(os.stat(path).st_mtime): # Read Data from csv file cot = pd.read_csv(path, index_col=0, parse_dates=True) else: if cot_type in cot_types: try: qdl_code = oci.get(stem, 'COT') cot = qdl.get('CFTC/{}_{}_ALL'.format(qdl_code, cot_type)) cot.to_csv(path, header=True) except qdl.NotFoundError: log.error('Incorrect code for download: {}'.format(stem)) return None else: raise Exception('COT Type {} not defined!'.format(cot_type)) return cot
def point(symbol): """Calculate the point value :param symbol: String symbol - Customized ticker :return: Float Point Value for the future """ return oci.get(symbol[0:2], 'Point')
def calculate_stds(df, length=20): """Calculate standard deviations for the spread in the specified dataframe. Returns a dataframe with a few extra columns. This is to be used in Excel. :param df: DataFrame universe of traded symbols :param length: Length for the standard deviation :return: DataFrame with results """ log = logging.getLogger(__name__) df_stds = [] for idx, row in df.iterrows(): ticker = row['Ticker'] log.debug('Process spread: {}'.format(ticker)) # STD dfm = odu.get_market_df(ticker) if dfm is not None: dfm = dfm.tail(length) std = dfm['Close'].std() else: std = 0 # COT cdf = odc.cot_data(ticker[0:2]) hps = cdf.iloc[-1]['HPS'] hph = cdf.iloc[-1]['HPH'] # Add data df_stds.append({'Ticker': ticker, 'LastDate': row['LastDate'], 'DaysTo': row['DaysTo'], 'HPS': hps, 'HPH': hph, 'PVol': std, 'IVol': std * i.get(ticker[0:2], 'Point')}) # Return dataframe return pd.DataFrame(df_stds, columns=['Ticker', 'LastDate', 'DaysTo', 'HPS', 'HPH', 'PVol', 'IVol'])
def __init__(self, stem, future_type): """Future Chain Constructor :param stem: str - Market Stem :param future_type: Enum FutureType - Type of contract """ self.log = logging.getLogger(__name__) self.stem = stem self.future_type = future_type self.status = None self.days_back = None self.chain = None self.contracts = None self.data = None self.margin = oci.get(stem, 'Margin') self.commission = oci.raw_comms(stem, dt.datetime.today()) self.point = oci.get(stem, 'Point')
def get_table(date, stem, future_type, status, we_trade=True, nac=4, ncb=1, data_download=False): """Generate a table of all the contracts available for a market and the associated last date. :param date: str - Date reference for the active or expired contracts :param stem: str - Market Stem :param future_type: Enum FutureType - Type of contract :param status: Enum Status - Status needed for the chain :param we_trade: bool - Whether or not the contract is considered as traded :param nac: int - Number of active contracts to get (depending on the markets) :param ncb: int - Number of contracts in between (not for outrights) :param data_download: bool - Option for data download (as we need to use LTD for completeness) :return: A dataframe of all the available tickers with the last date """ ld_rule = 'LTD' if data_download else oci.get(stem, 'Reference') # Get the contract table ct_df = oci.ctrmth(stem, we_trade) # Generate the contracts contracts = [] active = 0 min_ctrmth = 20000000 if future_type == oci.FutureType.Outright else 20070000 for index, row in ct_df[ct_df['CtrMth'] > min_ctrmth].iterrows(): cts = generate_contracts(stem, row['CtrMth'], future_type, ct_df, ncb) for c in cts: if not isinstance(row[ld_rule], str): raise ChainError('Problem in CtrMth table for: {}!'.format(c)) # Add 5 days to the end if ActivePlus Status (to continue downloading data for expired contracts) end = ( dt.datetime.strptime(row[ld_rule], '%Y-%m-%d') + o.BDay(5) ).strftime( '%Y-%m-%d') if status == Status.ActivePlus else row[ld_rule] # Add the contract depending on the status if status == Status.Active or status == Status.ActiveLive or status == Status.ActivePlus: if date > end or active >= nac * ncb: continue if date < row[ ld_rule]: # Not counting expired contracts for data download in ActivePlus mode active += 1 elif status == Status.Expired and date < row[ld_rule]: break # Add the contract to the list of contracts contracts.append( co.OrderedDict({ 'Ticker': c, 'LastDate': row[ld_rule] })) return pd.DataFrame(contracts)
def date(self, ticker, last_day, days): try: sl_type = oci.get(ticker[0:2], 'Spot') except oci.InstrumentError: raise EventsError('Spot Limit not defined in database.json!') if sl_type == 'Close of trading on the first business day of the contract month': return self._close_first_business_day(ticker, days) elif sl_type == 'During the last x trading days of the contract': nb = oci.get(ticker[0:2], 'Rule') return self._last_x_business_days(last_day, -nb + days) elif sl_type == 'x Business Day following the expiration of the regular option contract traded on the expiring futures contract': nb = oci.get(ticker[0:2], 'Rule') return self._x_business_days_after_third_friday( last_day, nb + days) elif sl_type == 'Close of trading x business days prior to last trading day of the contract': nb = oci.get(ticker[0:2], 'Rule') return self._last_x_business_days(last_day, -nb + days) elif sl_type == 'Close of trading on the business day prior to the first notice day of the delivery month': nb = oci.get(ticker[0:2], 'Rule') return self._close_first_business_day(ticker, -nb + days) elif sl_type == 'Close of trading x business days prior to the first trading day of the delivery month': nb = oci.get(ticker[0:2], 'Rule') return self._close_first_business_day(ticker, -nb + days) elif sl_type == 'On and after First Notice Day': return self._on_fnd(last_day, days) else: raise EventsError('Spot Limit function not defined!')
def generate_tickers_df(stem, status=occ.Status.Active): """Generate a DataFrame of symbols for a given stem for data download :param stem: str - Customized Stem :param status: Enum Status - Status needed for download :return: DataFrame with Ticker Column """ log = logging.getLogger(__name__) dfs = [] # Get number of active contracts and number of contracts in between # TODO: Populate database.json with values for all contracts! try: dl = oci.get(stem, 'Download') nac, ncb = dl['nac'], dl['ncb'] except oci.InstrumentError: log.warning('{} - Set Download Parameters!'.format(stem)) nac, ncb = 4, 1 # Default behaviour when no parameters params = {'as_dataframe': True, 'data_download': True} ot = occ.FutureChain(stem, oci.FutureType.Outright).initialize_contracts( status, we_trade=False, nac=nac, **params) st = occ.FutureChain(stem, oci.FutureType.Spread).initialize_contracts( status, we_trade=(False if stem != 'ED' else True), nac=nac - 1, ncb=ncb, **params) bt = occ.FutureChain(stem, oci.FutureType.Butterfly).initialize_contracts( status, we_trade=True, nac=nac - 2, ncb=ncb, **params) if stem == 'ED' else None dfs.append(ot) dfs.append(st) if bt is not None: dfs.append(bt) sdf = pd.concat(dfs) return sdf.reset_index(drop=True)
def add_tick(self): # TODO: ED has half tick (implement if needed) self.row.append(i.get(self.ticker[0:2], 'Tick'))