def test_roll_with_date(self): roll_data = rollParameters(priced_rollcycle="HMUZ", hold_rollcycle="Z", approx_expiry_offset=15) rollwithdate = contractDateWithRollParameters(roll_data, "201801") self.assertRaises(Exception, rollwithdate.next_priced_contract) roll_data_no_price_cycle = rollParameters(hold_rollcycle="F", approx_expiry_offset=15) rollwithdate = contractDateWithRollParameters(roll_data, "201801") self.assertRaises(Exception, rollwithdate.next_priced_contract) roll_data = rollParameters(priced_rollcycle="HMUZ", hold_rollcycle="MZ", approx_expiry_offset=15) rollwithdate = contractDateWithRollParameters(roll_data, "201806") self.assertEqual(rollwithdate.contract_date, "20180600") self.assertEqual(rollwithdate.expiry_date, datetime.datetime(2018,6,16)) self.assertEqual(rollwithdate.check_if_expiry_after_date(datetime.datetime(2018,1,1)), True) next_held = rollwithdate.next_held_contract() prior_held = rollwithdate.previous_held_contract() next_priced = rollwithdate.next_priced_contract() prior_priced = rollwithdate.previous_priced_contract() self.assertEqual(next_held.contract_date, "20181200") self.assertEqual(prior_held.contract_date, "20171200") self.assertEqual(next_priced.contract_date, "20180900") self.assertEqual(prior_priced.contract_date, "20180300")
def _generate_approximate_calendar(list_of_contract_dates, roll_parameters_object): """ Using a rollData object we work out roughly what the rolls should be (in an ideal world with available prices all the time) for contracts held between start_date and end_date Called by __init__ :param list_of_contracts: list of contract_date ids, eg 'yyyymmdd' :param roll_parameters_object: rollData :return: data frame ready to be rollCalendar """ list_of_contract_dates.sort() plausible_earliest_contract_date = list_of_contract_dates[0] plausible_earliest_contract_with_roll_data = contractDateWithRollParameters(roll_parameters_object, plausible_earliest_contract_date) # We do this in case the first contract in the data isn't in the roll cycle earliest_contract_with_roll_data = plausible_earliest_contract_with_roll_data.first_valid_held_contract() final_contract_date = list_of_contract_dates[-1] final_contract_with_roll_data = contractDateWithRollParameters(roll_parameters_object, final_contract_date) final_roll_date = final_contract_with_roll_data.want_to_roll() current_contract = earliest_contract_with_roll_data theoretical_roll_dates=[] contracts_to_hold_on_each_roll = [] # On the roll date we stop holding the current contract, and end up holding the next one # The roll date is the last day we hold the current contract while current_contract.want_to_roll() <= final_roll_date: # No point adding a non existent contract try: assert current_contract.contract_date in list_of_contract_dates except: raise Exception("Missing roll date %s from data when building roll calendar using hold calendar %s" % (current_contract.contract_date, str(roll_parameters_object.hold_rollcycle))) current_roll_date = current_contract.want_to_roll() theoretical_roll_dates.append(current_roll_date) contracts_to_hold_on_each_roll.append(current_contract) current_contract = current_contract.next_held_contract() # We don't know what the next contract will be so we drop the final one contract_dates_to_hold_on_each_roll = [contract.contract_date for contract in contracts_to_hold_on_each_roll[:-1]] # We also need a list of the next contract along next_contract_along = contracts_to_hold_on_each_roll[1:] contract_dates_next_contact_along = [contract.contract_date for contract in next_contract_along] # we don't know what the next contract will be, so we drop the last roll date theoretical_roll_dates = theoretical_roll_dates[:-1] roll_calendar = pd.DataFrame(dict(current_contract = contract_dates_to_hold_on_each_roll, next_contract = contract_dates_next_contact_along), index = theoretical_roll_dates) return roll_calendar
def get_contract_chain(instrument_code, data): diag_contracts = diagContracts(data) diag_prices = diagPrices(data) roll_parameters = diag_contracts.get_roll_parameters(instrument_code) # Get the last contract currently being used multiple_prices = diag_prices.get_multiple_prices(instrument_code) current_contract_dict = multiple_prices.current_contract_dict() current_contract_list = list(current_contract_dict.values()) furthest_out_contract_date = max(current_contract_list) furthest_out_contract = contractDateWithRollParameters( roll_parameters, furthest_out_contract_date) # To give us wiggle room, and ensure we start collecting the new forward a # little in advance final_contract = furthest_out_contract.next_priced_contract() contract_date_chain = ( final_contract.get_unexpired_contracts_from_now_to_contract_date()) # We have a list of contract_date objects, need futureContracts # create a 'bare' instrument object instrument_object = futuresInstrument(instrument_code) contract_object_chain_as_list = [ futuresContract(instrument_object, contract_date_object) for contract_date_object in contract_date_chain ] contract_object_chain = listOfFuturesContracts( contract_object_chain_as_list) return contract_object_chain
def _add_carry_calendar(roll_calendar, roll_parameters_object, dict_of_futures_contract_prices): """ :param roll_calendar: pdDataFrame with current_contract and next_contract :param roll_parameters_object: rollData :return: data frame ready to be rollCalendar """ list_of_contract_dates = list(roll_calendar.current_contract.values) contracts_with_roll_data = [ contractDateWithRollParameters(roll_parameters_object, str(contract_date)) for contract_date in list_of_contract_dates ] carry_contract_dates = [ contract.carry_contract().contract_date for contract in contracts_with_roll_data ] ## Special case if first carry contract missing with a negative offset first_carry_contract = carry_contract_dates[0] if first_carry_contract not in dict_of_futures_contract_prices: # drop the first roll entirely carry_contract_dates.pop(0) # do the same with the calendar or will misalign first_roll_date = roll_calendar.index[0] roll_calendar = roll_calendar.drop(first_roll_date) roll_calendar['carry_contract'] = carry_contract_dates return roll_calendar
def _generate_approximate_calendar(list_of_contract_dates, roll_parameters_object): """ Using a rollData object we work out roughly what the rolls should be (in an ideal world with available prices all the time) for contracts held between start_date and end_date Called by __init__ :param list_of_contracts: list of contract_date ids, eg 'yyyymmdd' :param roll_parameters_object: rollData :return: data frame ready to be rollCalendar """ contracts_with_roll_data = [contractDateWithRollParameters(roll_parameters_object, contract_date) for contract_date in list_of_contract_dates] theoretical_roll_dates=[contract_date.want_to_roll() for contract_date in contracts_with_roll_data] # On the roll date we stop holding the current contract, and end up holding the next one contracts_to_hold_on_each_roll = contracts_with_roll_data[:-1] contract_dates_to_hold_on_each_roll = [contract.contract_date for contract in contracts_to_hold_on_each_roll] # We also need a list of the next contract along next_contract_along = contracts_with_roll_data[1:] contract_dates_next_contact_along = [contract.contract_date for contract in next_contract_along] # we don't know what the next contract will be, so we drop the last roll date theoretical_roll_dates = theoretical_roll_dates[:-1] roll_calendar = pd.DataFrame(dict(current_contract = contract_dates_to_hold_on_each_roll, next_contract = contract_dates_next_contact_along), index = theoretical_roll_dates) return roll_calendar
def get_contract_date_object_with_roll_parameters(self, instrument_code, contract_date_id): roll_parameters = self.get_roll_parameters(instrument_code) contract_date_with_roll_parameters = contractDateWithRollParameters( roll_parameters, contract_date_id) return contract_date_with_roll_parameters
def extend_current_contracts(self, instrument_code, current_contracts): price_contract_date = current_contracts['PRICE'] forward_contract_date = current_contracts['FORWARD'] carry_contract_date = current_contracts['CARRY'] price_contract_date, forward_contract_date, carry_contract_date roll_parameters = self.get_roll_parameters(instrument_code) price_contract = contractDateWithRollParameters( roll_parameters, price_contract_date) forward_contract = contractDateWithRollParameters( roll_parameters, forward_contract_date) carry_contract = contractDateWithRollParameters( roll_parameters, carry_contract_date) preceeding_price_contract_date = price_contract.previous_priced_contract( ) preceeding_forward_contract_date = forward_contract.previous_priced_contract( ) subsequent_forward_contract_date = forward_contract.next_held_contract( ) # Could be up to 6 contracts # HOW TO PAD THESE ? all_contracts = [ price_contract, forward_contract, preceeding_forward_contract_date, preceeding_price_contract_date, subsequent_forward_contract_date, carry_contract ] all_contracts_dates = [ contract.contract_date for contract in all_contracts ] unique_all_contract_dates = list(set(all_contracts_dates)) unique_all_contract_dates.sort() unique_all_contract_dates = unique_all_contract_dates + [ missing_contract ] * (6 - len(unique_all_contract_dates)) return unique_all_contract_dates
def historical_price_contracts(listOfFuturesContracts, instrument_object, roll_parameters, first_contract_date, end_date=datetime.datetime.now()): """ We want to get all the contracts that fit in the roll cycle, bearing in mind the RollOffsetDays (in roll_parameters) So for example suppose we want all contracts since 1st January 1980, to the present day, for Eurodollar; where the rollcycle = "HMUZ" (quarterly IMM) and where the rollOffSetDays is 1100 (we want to be around 3 years in the future; eg 12 contracts). If it's current 1st January 2018 then we'd get all contracts with expiries between 1st January 1980 to approx 1st January 2021 This uses the 'priceRollCycle' rollCycle in instrument_object, which is a superset of the heldRollCycle :param instrument_object: An instrument object :param roll_parameters: rollParameters :param start_date: The first contract date, 'eg yyyymm' :param end_date: The date when we want to stop getting data, defaults to today :return: list of futuresContracts """ first_contract = futuresContract(instrument_object, contractDateWithRollParameters(roll_parameters, first_contract_date)) assert end_date > first_contract.expiry_date current_held_contract = futuresContract.approx_first_held_futuresContract_at_date(instrument_object, roll_parameters, end_date) current_priced_contract = futuresContract.approx_first_priced_futuresContract_at_date(instrument_object, roll_parameters, end_date) current_carry_contract = current_held_contract.carry_contract() # these are all str thats okay last_contract_date = max([current_held_contract.date, current_priced_contract.date, current_carry_contract.date]) list_of_contracts = [first_contract] ## note the same instrument_object will be shared by all in the list so we can modify it directly if needed date_still_valid = True current_contract = first_contract while date_still_valid: next_contract = current_contract.next_priced_contract() list_of_contracts.append(next_contract) if next_contract.date >= last_contract_date: date_still_valid = False # will now terminate if len(list_of_contracts)>MAX_CONTRACT_SIZE: raise Exception("Too many contracts - check your inputs") current_contract = next_contract return listOfFuturesContracts(list_of_contracts)
def test_roll_with_date(self): roll_data = rollParameters(priced_rollcycle="HMUZ", hold_rollcycle="Z", contract_offset=1, approx_expiry_offset=15) rollwithdate = contractDateWithRollParameters(roll_data, "201801") self.assertRaises(Exception, rollwithdate.next_priced_contract) roll_data_no_price_cycle = rollParameters(hold_rollcycle="F", contract_offset=1, approx_expiry_offset=15) rollwithdate = contractDateWithRollParameters(roll_data, "201801") self.assertRaises(Exception, rollwithdate.next_priced_contract) roll_data = rollParameters(priced_rollcycle="HMUZ", hold_rollcycle="MZ", contract_offset=1, approx_expiry_offset=15) rollwithdate = contractDateWithRollParameters(roll_data, "201806") self.assertEqual(rollwithdate.contract_date, "20180600") self.assertEqual(rollwithdate.expiry_date, datetime.datetime(2018, 6, 16)) self.assertEqual( rollwithdate.check_if_expiry_after_date( datetime.datetime(2018, 1, 1)), True) next_held = rollwithdate.next_held_contract() prior_held = rollwithdate.previous_held_contract() next_priced = rollwithdate.next_priced_contract() prior_priced = rollwithdate.previous_priced_contract() self.assertEqual(next_held.contract_date, "20181200") self.assertEqual(prior_held.contract_date, "20171200") self.assertEqual(next_priced.contract_date, "20180900") self.assertEqual(prior_priced.contract_date, "20180300")
def _generate_approximate_calendar(list_of_contract_dates, roll_parameters_object): """ Using a rollData object we work out roughly what the rolls should be (in an ideal world with available prices all the time) for contracts held between start_date and end_date Called by __init__ :param list_of_contracts: list of contract_date ids, eg 'yyyymmdd' :param roll_parameters_object: rollData :return: data frame ready to be rollCalendar """ contracts_with_roll_data = [ contractDateWithRollParameters(roll_parameters_object, contract_date) for contract_date in list_of_contract_dates ] theoretical_roll_dates = [ contract_date.want_to_roll() for contract_date in contracts_with_roll_data ] # On the roll date we stop holding the current contract, and end up holding the next one contracts_to_hold_on_each_roll = contracts_with_roll_data[:-1] contract_dates_to_hold_on_each_roll = [ contract.contract_date for contract in contracts_to_hold_on_each_roll ] # We also need a list of the next contract along next_contract_along = contracts_with_roll_data[1:] contract_dates_next_contact_along = [ contract.contract_date for contract in next_contract_along ] # we don't know what the next contract will be, so we drop the last roll date theoretical_roll_dates = theoretical_roll_dates[:-1] roll_calendar = pd.DataFrame(dict( current_contract=contract_dates_to_hold_on_each_roll, next_contract=contract_dates_next_contact_along), index=theoretical_roll_dates) return roll_calendar
def _add_carry_calendar(roll_calendar, roll_parameters_object): """ :param roll_calendar: pdDataFrame with current_contract and next_contract :param roll_parameters_object: rollData :return: data frame ready to be rollCalendar """ list_of_contract_dates = list(roll_calendar.current_contract.values) contracts_with_roll_data = [contractDateWithRollParameters(roll_parameters_object, str(contract_date)) for contract_date in list_of_contract_dates] carry_contracts = [contract.carry_contract().contract_date for contract in contracts_with_roll_data] roll_calendar['carry_contract'] = carry_contracts return roll_calendar
def _add_carry_calendar(roll_calendar, roll_parameters_object): """ :param roll_calendar: pdDataFrame with current_contract and next_contract :param roll_parameters_object: rollData :return: data frame ready to be rollCalendar """ list_of_contract_dates = list(roll_calendar.current_contract.values) contracts_with_roll_data = [ contractDateWithRollParameters(roll_parameters_object, str(contract_date)) for contract_date in list_of_contract_dates ] carry_contracts = [ contract.carry_contract().contract_date for contract in contracts_with_roll_data ] roll_calendar['carry_contract'] = carry_contracts return roll_calendar