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 test_generate_contracts(stem, ctr_mth, future_type, ncb): df = oci.ctrmth(stem, True) lc = occ.generate_contracts(stem, ctr_mth, future_type, df, ncb) print(lc) # Check if list is returned assert isinstance(lc, list) # Check if length list is as expected if future_type == oci.FutureType.Outright: assert len(lc) == 1 else: assert len(lc) == ncb # Check if an element is a string (if it is it must be a ticker) assert isinstance(lc[0], str)
def generate_curvature_list(): """Generate a list of symbols for data download for the curvature strategy. This is to be used only to generate the symbols for the Excel Quotes sheet. :return: list - Active Tickers for ED and FF """ log = logging.getLogger(__name__) log.debug('Generate list of tickers for Curvature') date = dt.datetime.today().strftime('%Y-%m-%d') tickers = [] for m in ['ED', 'FF']: mcm = oci.ctrmth(m) fm = mcm[mcm['LTD'] >= date].iloc[0]['CtrMth'] tickers.extend( generate_tickers_for_curvature(oci.ym_maturity(fm), m, 1 if m == 'FF' else 3)) # Transform to short maturities (specific to Curvature) tickers = ['{}{}'.format(t[0:-2], t[-1]) for t in tickers] return tickers
def amend_ctrmth(stem, amendments): """Amend the Contract Month table - This is a hard amend, as is, the old file will be overwritten with the changes. Must provide tuples of letters and status. :param stem: str - Customized Stem :param amendments: list - List of tuples (example: [('J', True)] """ log = logging.getLogger(__name__) df = oci.ctrmth(stem, we_trade=False) # Amendments for a in amendments: df.loc[df['Letter'] == a[0], 'WeTrd'] = (-1 if a[1] else 0) log.debug('CtrMth table updated for: {} - Changes: {}'.format(stem, amendments)) # Save new Contract Month table ric = oci.get_stem(stem, 'Reuters') file = os.path.join(c.cfg['default']['data'], 'CtrMth', '{}.csv'.format(ric)) fields = ['CtrMth', 'WeTrd', 'LTD', 'FND', 'PosFstDt', 'PosLstDt'] df[fields].to_csv(file, sep=',', index=False, header=True)
def per_contract(future_chain, field='Volume'): """Plot heatmap of the average Volume or Open Interest of the last 90 days. Display it by year for each contract. This should be useful to find out which contract are traded/not traded and where :param future_chain: object - Future Chain initialized with data :param field: str - Volume or OI :return: object - Plot Plotly chart """ log = logging.getLogger(__name__) if field != 'Volume' and field != 'OI': raise Exception('Field provided must be str Volume or OI!') stem = future_chain.stem df = future_chain.chain data = future_chain.data # Average Volume df['Month'] = df.apply(lambda x: x['Ticker'][2:3], axis=1) df['Year'] = df.apply(lambda x: 2000 + int(x['Ticker'][-2:]), axis=1) # Add average volume of last 90 days df['AvgVol'] = 0 for idx, row in df.iterrows(): mdf = data[row['Ticker']] df.loc[idx, 'AvgVol'] = int(mdf[-90:][field].mean()) # Transformation to HeatMap DF years = [] for year in df['Year'].unique(): ydf = df[df['Year'] == year][['Month', 'AvgVol']] ydf.set_index('Month', drop=True, inplace=True) ydf.index.names = [None] ydf.columns = [year] years.append(ydf) hdf = pd.concat(years, axis=1) # Index cdf = oci.ctrmth(stem, we_trade=False) cdf['Letter'] = cdf.apply(lambda x: oci.ym_maturity(x['CtrMth'])[0], axis=1) lw = cdf.groupby('Letter').mean() lw['Index'] = lw.apply(lambda x: '{} (T: {})'.format(x.name, x['WeTrd']), axis=1) rlw = lw.reindex(index=lw.index[::-1]) # Plot rhdf = hdf.reindex(index=hdf.index[::-1]) values = rhdf.values values = [[int(vi) if not math.isnan(vi) else float('NaN') for vi in v] for v in values] try: fig = pff.create_annotated_heatmap(values, x=list(rhdf.columns), y=list(rlw['Index']), colorscale='Jet', font_colors=['white'], hoverinfo='z') for i in range(len(fig.layout.annotations)): # Make text size smaller fig.layout.annotations[i].font.size = 10 fig.layout.title = '{} - {}'.format(stem, field) plo.iplot(fig) except ple.PlotlyError: log.error( 'Most likely a problem with axis length: x: {} - y: {} - z: {}'. format(list(rhdf.columns), list(rlw['Index']), len(values)))
def test_ctrmth(stem, we_trade): df = oci.ctrmth(stem, we_trade) assert isinstance(df, pd.DataFrame) print(df.head())