def update_historical_prices_for_instrument_and_contract(
        contract_object: futuresContract, data: dataBlob):
    """
    Do a daily update for futures contract prices, using IB historical data

    There are two different calls, the first using intraday frequency, the second daily.
    So in a typical session we'd get the hourly intraday prices for a given instrument,
    and then if that instrument has closed we'd also get a new end of day price.
    The end of day prices are given the artifical datetime stamp of 23:00:00
    (because I never collect data round that time).

    If the intraday call fails, we don't want to get daily data.
    Otherwise we wouldn't be able to subsequently backfill hourly prices that occured
    before the daily close being added (the code doesn't allow you to add prices that have
    a timestamp which is before the last timestamp in the existing data).

    That's why the result of the first call matters, and is used to abort the function prematurely before we get to daily data.
    We don't care about the second call succeeding or failing, and so the result of that is ignored.

    :param contract_object: futuresContract
    :param data: data blob
    :return: None
    """
    diag_prices = diagPrices(data)
    intraday_frequency = diag_prices.get_intraday_frequency_for_historical_download(
    )
    daily_frequency = DAILY_PRICE_FREQ

    # Get *intraday* data (defaults to hourly)
    result = get_and_add_prices_for_frequency(data,
                                              contract_object,
                                              frequency=intraday_frequency)
    if result is failure:
        # Skip daily data if intraday not working

        return None

    # Get daily data
    # we don't care about the result flag for this
    get_and_add_prices_for_frequency(data,
                                     contract_object,
                                     frequency=daily_frequency)
def update_multiple_adjusted_prices_for_instrument(instrument_code, data):
    """
    Update for multiple and adjusted prices for a given instrument

    :param instrument_code:
    :param data: dataBlob
    :param log: logger
    :return: None
    """

    log = data.log.setup(instrument_code=instrument_code)
    diag_prices = diagPrices(data)
    update_prices = updatePrices(data)
    # update multiple prices with new prices
    # (method in multiple prices object and possible in data socket)
    existing_adjusted_prices = diag_prices.get_adjusted_prices(instrument_code)
    existing_multiple_prices = diag_prices.get_multiple_prices(instrument_code)

    relevant_contracts = existing_multiple_prices.current_contract_dict()

    new_prices_dict = get_dict_of_new_prices_and_contractid(
        instrument_code, relevant_contracts, data)
    updated_multiple_prices = existing_multiple_prices.update_multiple_prices_with_dict(
        new_prices_dict)

    updated_adjusted_prices = existing_adjusted_prices.update_with_multiple_prices_no_roll(
        updated_multiple_prices)

    if updated_adjusted_prices is no_update_roll_has_occured:
        log.critical(
            "Can't update adjusted prices for %s as roll has occured but not registered properly"
            % instrument_code)
        raise Exception()

    update_prices.add_multiple_prices(instrument_code,
                                      updated_multiple_prices,
                                      ignore_duplication=True)
    update_prices.add_adjusted_prices(instrument_code,
                                      updated_adjusted_prices,
                                      ignore_duplication=True)

    return success
def calculate_adjusted_price_for_a_direct_child_order(
    data: dataBlob,
        child_order: contractOrder,
        original_contract_date: str,
        original_price: float
) -> float:
    """

    :param data:
    :param child_order:
    :param original_contract_date:
    :param original_price:
    :return: float or missing data
    """
    instrument_code = child_order.instrument_code
    try:
        assert not child_order.calendar_spread_order
    except BaseException:
        raise Exception(
            "You have tried to adjust the price for a spread contract order assuming it is a single leg order"
        )

    child_contract_date = child_order.contract_date_key

    if original_contract_date == child_contract_date:
        return original_price

    diag_prices = diagPrices(data)
    contract_list = [original_contract_date, child_contract_date]
    _last_matched_date, list_of_matching_prices = diag_prices.get_last_matched_date_and_prices_for_contract_list(
        instrument_code, contract_list
    )
    differential = list_of_matching_prices[1] - list_of_matching_prices[0]

    if np.isnan(differential):
        # can't adjust
        # note need to test code there may be other ways in which this fails
        return missing_data

    adjusted_price = original_price + differential

    return adjusted_price
Beispiel #4
0
def get_dates_to_choose_from(
        data: dataBlob,
        instrument_code: str,
        only_priced_contracts: bool = False) -> listOfContractDateStr:

    diag_contracts = dataContracts(data)
    diag_prices = diagPrices(data)
    if only_priced_contracts:
        dates_to_choose_from = (
            diag_prices.contract_dates_with_price_data_for_instrument_code(
                instrument_code))
    else:
        contract_list = diag_contracts.get_all_contract_objects_for_instrument_code(
            instrument_code)
        dates_to_choose_from = contract_list.list_of_dates()

    dates_to_choose_from = listOfContractDateStr(dates_to_choose_from)
    dates_to_choose_from = dates_to_choose_from.sorted_date_str()

    return dates_to_choose_from
Beispiel #5
0
def get_liquidity_data_df(data: dataBlob):
    diag_prices = diagPrices(data)

    instrument_list = diag_prices.get_list_of_instruments_with_contract_prices(
    )

    print("Getting data... patience")
    p = progressBar(len(instrument_list))
    all_liquidity = []
    for instrument_code in instrument_list:
        p.iterate()
        liquidity_this_instrument = get_liquidity_dict_for_instrument_code(
            data, instrument_code)
        all_liquidity.append(liquidity_this_instrument)

    all_liquidity_df = pd.DataFrame(all_liquidity)
    all_liquidity_df.index = instrument_list
    all_liquidity_df["contracts"] = all_liquidity_df["contracts"].round(0)

    return all_liquidity_df
Beispiel #6
0
def update_historical_prices_with_checks_for_instrument_and_contract(
    contract_object, data, log
):
    """
    Do a daily update for futures contract prices, using IB historical data, with checking

    :param contract_object: futuresContract
    :param data: data blob
    :param log: logger
    :return: None
    """
    diag_prices = diagPrices(data)
    intraday_frequency = diag_prices.get_intraday_frequency_for_historical_download()
    get_and_check_prices_for_frequency(
        data, log, contract_object, frequency=intraday_frequency
    )
    get_and_check_prices_for_frequency(
        data, log, contract_object, frequency="D")

    return success
def calc_update_adjusted_prices(
        data: dataBlob, instrument_code: str,
        updated_multiple_prices: futuresMultiplePrices
) -> futuresAdjustedPrices:

    diag_prices = diagPrices(data)
    existing_adjusted_prices = diag_prices.get_adjusted_prices(instrument_code)

    updated_adjusted_prices = (
        existing_adjusted_prices.update_with_multiple_prices_no_roll(
            updated_multiple_prices))

    if updated_adjusted_prices is no_update_roll_has_occured:
        msg = (
            "Can't update adjusted prices for %s as roll has occured but not registered properly"
            % instrument_code)
        data.log.critical(msg)
        raise Exception(msg)

    return updated_adjusted_prices
def get_list_of_instruments_to_auto_cycle(data: dataBlob, days_ahead: int = 10) -> list:

    diag_prices = diagPrices()
    list_of_potential_instruments = (
        diag_prices.get_list_of_instruments_in_multiple_prices()
    )
    instrument_list = [
        instrument_code
        for instrument_code in list_of_potential_instruments
        if include_instrument_in_auto_cycle(
            data=data, instrument_code=instrument_code, days_ahead=days_ahead
        )
    ]

    print_with_landing_strips_around(
        "Identified following instruments that are near expiry %s"
        % str(instrument_list)
    )

    return instrument_list
Beispiel #9
0
def get_valid_instrument_code_and_contractid_from_user(
        data, instrument_code=None, include_priced_contracts=False):
    diag_contracts = diagContracts(data)
    diag_prices = diagPrices(data)

    invalid_input = True
    while invalid_input:
        if instrument_code is None:
            instrument_code = get_valid_instrument_code_from_user(
                data, source='single')

        if include_priced_contracts:
            dates_to_choose_from = diag_prices.contract_dates_with_price_data_for_instrument_code(
                instrument_code)
        else:
            contract_list = diag_contracts.get_all_contract_objects_for_instrument_code(
                instrument_code)
            dates_to_choose_from = contract_list.list_of_dates()

        dates_to_display = diag_contracts.get_labelled_list_of_contracts_from_contract_date_list(
            instrument_code, dates_to_choose_from)

        if len(dates_to_choose_from) == 0:
            print("%s is not an instrument with contract data" %
                  instrument_code)
            instrument_code = None
            continue
        print("Available contract dates %s" % str(dates_to_display))
        print("p = currently priced, c=current carry, f= current forward")
        contract_date = input(
            "Contract date? [yyyymm or yyyymmdd] (ignore suffixes)")
        if len(contract_date) == 6:
            contract_date = contract_date + "00"
        if contract_date in dates_to_choose_from:
            break
        else:
            print("%s is not in list %s" %
                  (contract_date, dates_to_choose_from))
            continue  # not required

    return instrument_code, contract_date
Beispiel #10
0
def update_historical_prices_for_instrument_and_contract(
        contract_object: futuresContract,
        data: dataBlob,
        cleaning_config: priceFilterConfig = arg_not_supplied,
        interactive_mode: bool = False):

    diag_prices = diagPrices(data)
    intraday_frequency = diag_prices.get_intraday_frequency_for_historical_download(
    )
    daily_frequency = DAILY_PRICE_FREQ

    # Get *intraday* data (defaults to hourly)
    result = get_and_add_prices_for_frequency(
        data,
        contract_object,
        frequency=intraday_frequency,
        cleaning_config=cleaning_config,
        interactive_mode=interactive_mode)
    if result is failure:
        # Skip daily data if intraday not working
        if cleaning_config.dont_sample_daily_if_intraday_fails:
            data.log.msg(
                "Had a problem samping intraday, skipping daily to avoid price gaps"
            )
            return failure
        else:
            data.log.warn(
                "Had a problem samping intraday, but **NOT** skipping daily - may be price gaps"
            )

    # Get daily data
    # we don't care about the result flag for this
    get_and_add_prices_for_frequency(
        data,
        contract_object,
        frequency=daily_frequency,
        cleaning_config=cleaning_config,
        interactive_mode=interactive_mode,
    )

    return success
Beispiel #11
0
def vol_calculations_for_slippage_row(slippage_row, data):
    ## What's a tick worth in base currency?
    diag_prices = diagPrices(data)
    rolling_daily_vol = diag_prices.get_quick_std_of_adjusted_prices(
        slippage_row.instrument_code)
    if len(rolling_daily_vol) == 0:
        last_daily_vol = np.nan
    else:
        last_daily_vol = rolling_daily_vol.ffill().values[-1]
    last_annual_vol = last_daily_vol * 16

    input_items = [
        'delay', 'bid_ask', 'execution', 'versus_limit', 'versus_parent_limit',
        'total_trading'
    ]
    output = [
        10000 * slippage_row[input_name] / last_annual_vol
        for input_name in input_items
    ]

    return tuple(output + [last_annual_vol])
Beispiel #12
0
def interactive_manual_check_historical_prices(instrument_code: str):
    """
    Do a daily update for futures contract prices, using IB historical data

    If any 'spikes' are found, run manual checks

    :return: Nothing
    """
    with dataBlob(log_name="Update-Historical-prices-manually") as data:
        diag_prices = diagPrices(data)
        list_of_codes_all = diag_prices.get_list_of_instruments_with_contract_prices()
        if instrument_code not in list_of_codes_all:
            print(
                "\n\n\ %s is not an instrument with price data \n\n" %
                instrument_code)
            raise Exception()
        update_historical_prices_with_checks_for_instrument(
            instrument_code, data, log=data.log.setup(
                instrument_code=instrument_code))

    return success
Beispiel #13
0
def get_dict_of_new_prices_and_contractid(instrument_code, contract_date_dict,
                                          data):
    """

    :param instrument_code: str
    :param contract_list: dict of 'yyyymmdd' str, keynames 'CARRY, PRICE, FORWARD'
    :param data:
    :return: dict of futures contract prices for each contract, plus contract id column
    """
    diag_prices = diagPrices(data)
    # get prices for relevant contracts, return as dict labelled with column for contractids
    relevant_contract_prices = dict()
    for key, contract_date in contract_date_dict.items():
        price_series = diag_prices.get_prices_for_instrument_code_and_contract_date(
            instrument_code, contract_date)
        relevant_contract_prices[key] = price_series.return_final_prices()

    new_prices_dict = dictFuturesContractFinalPricesWithContractID.\
        create_from_two_dicts(relevant_contract_prices, contract_date_dict)

    return new_prices_dict
Beispiel #14
0
def create_contract_orders_spread(data, instrument_code, priced_contract_id,
                                  forward_contract_id, position_in_priced):

    diag_prices = diagPrices(data)
    reference_price_priced_contract, reference_price_forward_contract = \
        tuple(diag_prices.get_last_matched_prices_for_contract_list(
            instrument_code, [priced_contract_id, forward_contract_id]))

    strategy = ROLL_PSEUDO_STRATEGY
    contract_id_list = [priced_contract_id, forward_contract_id]
    trade_list = [-position_in_priced, position_in_priced]
    spread_reference_price = reference_price_priced_contract - reference_price_forward_contract

    spread_order = contractOrder(strategy,
                                 instrument_code,
                                 contract_id_list,
                                 trade_list,
                                 reference_price=spread_reference_price,
                                 roll_order=True)

    return [spread_order]
Beispiel #15
0
def calculate_adjusted_price_for_a_direct_child_order(data, instrument_code,
                                                      child_order,
                                                      original_contract_date,
                                                      original_price):
    """

    :param data:
    :param instrument_code:
    :param child_order:
    :param original_contract_date:
    :param original_price:
    :return: float or missing data
    """

    try:
        assert len(child_order.contract_id) == 1
    except:
        raise Exception(
            "You have tried to adjust the price for a spread contract order assuming it is a direct order"
        )

    child_contract_date = child_order.contract_id[0]

    if original_contract_date == child_contract_date:
        return original_price

    diag_prices = diagPrices(data)
    contract_list = [original_contract_date, child_contract_date]
    list_of_prices = diag_prices.get_last_matched_prices_for_contract_list(
        instrument_code, contract_list)
    differential = list_of_prices[1] - list_of_prices[0]

    if np.isnan(differential):
        # can't adjust
        # note need to test code there may be other ways in which this fails
        return missing_data

    adjusted_price = original_price + differential

    return adjusted_price
Beispiel #16
0
def update_multiple_adjusted_prices_daily():
    """
    Do a daily update for multiple and adjusted prices

    :return: Nothing
    """

    with dataBlob(log_name="Update-multiple-adjusted-prices(daily)") as data:
        diag_prices = diagPrices(data)

        list_of_codes_all = diag_prices.get_list_of_instruments_in_multiple_prices(
        )
        for instrument_code in list_of_codes_all:
            try:

                update_multiple_adjusted_prices_for_instrument(
                    instrument_code, data)
            except Exception as e:
                data.log.warn("ERROR: Multiple price update went wrong: %s" %
                              str(e))

    return success
def update_historical_prices_for_instrument_and_contract(
        contract_object: futuresContract, data: dataBlob):
    """
    Do a daily update for futures contract prices, using IB historical data

    :param contract_object: futuresContract
    :param data: data blob
    :return: None
    """
    diag_prices = diagPrices(data)
    intraday_frequency = diag_prices.get_intraday_frequency_for_historical_download()
    daily_frequency = DAILY_PRICE_FREQ

    result = get_and_add_prices_for_frequency(
        data, contract_object, frequency=intraday_frequency
    )
    if result is failure:
        # Skip daily data if intraday not working
        return None

    get_and_add_prices_for_frequency(
        data, contract_object, frequency=daily_frequency)
Beispiel #18
0
def get_and_check_prices_for_frequency(
        data, log, contract_object, frequency="D"):

    broker_data = dataBroker(data)
    price_data = diagPrices(data)
    price_updater = updatePrices(data)

    try:
        old_prices = price_data.get_prices_for_contract_object(contract_object)
        ib_prices = broker_data.get_prices_at_frequency_for_contract_object(
            contract_object, frequency
        )
        if len(ib_prices) == 0:
            raise Exception(
                "No IB prices found for %s nothing to check" %
                str(contract_object))

        print(
            "\n\n Manually checking prices for %s \n\n" %
            str(contract_object))
        new_prices_checked = manual_price_checker(
            old_prices,
            ib_prices,
            column_to_check="FINAL",
            delta_columns=["OPEN", "HIGH", "LOW"],
            type_new_data=futuresContractPrices,
        )
        result = price_updater.update_prices_for_contract(
            contract_object, new_prices_checked, check_for_spike=False
        )
        return result

    except Exception as e:
        log.warn(
            "Exception %s when getting or checking data at frequency %s for %s"
            % (e, frequency, str(contract_object))
        )
        return failure
def get_trading_hours_for_all_instruments(data=arg_not_supplied):
    if data is arg_not_supplied:
        data = dataBlob()

    diag_prices = diagPrices(data)
    list_of_instruments = diag_prices.get_list_of_instruments_with_contract_prices()

    p = progressBar(len(list_of_instruments))
    all_trading_hours = {}
    for instrument_code in list_of_instruments:
        p.iterate()
        trading_hours = get_trading_hours_for_instrument(data, instrument_code)
        if trading_hours is missing_contract:
            print("*** NO EXPIRY FOR %s ***" % instrument_code)
            continue

        ## will have several days use first one
        check_trading_hours(trading_hours, instrument_code)
        all_trading_hours[instrument_code] = trading_hours

    p.finished()

    return all_trading_hours
Beispiel #20
0
def update_historical_prices_for_instrument_and_contract(
        contract_object, data, log):
    """
    Do a daily update for futures contract prices, using IB historical data

    :param contract_object: futuresContract
    :param data: data blob
    :param log: logger
    :return: None
    """
    diag_prices = diagPrices(data)
    intraday_frequency = diag_prices.get_intraday_frequency_for_historical_download()
    result = get_and_add_prices_for_frequency(
        data, log, contract_object, frequency=intraday_frequency
    )
    if result is failure:
        # Skip daily data if intraday not working
        return failure

    result = get_and_add_prices_for_frequency(
        data, log, contract_object, frequency="D")

    return result
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
Beispiel #22
0
def get_price_series_for_contract(data, instrument_code, contract_id):
    diag_prices = diagPrices(data)
    all_prices = diag_prices.get_prices_for_instrument_code_and_contract_date(instrument_code, contract_id)
    price_series = all_prices.return_final_prices()

    return price_series
def update_historical_prices_with_data(data: dataBlob):
    price_data = diagPrices(data)
    list_of_codes_all = price_data.get_list_of_instruments_in_multiple_prices()
    for instrument_code in list_of_codes_all:
        data.log.label(instrument_code=instrument_code)
        update_historical_prices_for_instrument(instrument_code, data)
Beispiel #24
0
def update_active_contracts_with_data(data: dataBlob):
    diag_prices = diagPrices(data)
    list_of_codes_all = diag_prices.get_list_of_instruments_in_multiple_prices()
    for instrument_code in list_of_codes_all:
        update_active_contracts_for_instrument(
            instrument_code, data)
Beispiel #25
0
def get_price_series(data, instrument_code):
    diag_prices = diagPrices(data)
    price_series = diag_prices.get_adjusted_prices(instrument_code)

    return price_series
Beispiel #26
0
def get_last_price(data: dataBlob, instrument_code: str):
    diag_prices = diagPrices(data)
    prices = diag_prices.get_adjusted_prices(instrument_code)

    return prices.ffill().values[-1]
Beispiel #27
0
    def _list_of_all_instruments(self):
        diag_prices = diagPrices(self.data)
        list_of_instruments = diag_prices.get_list_of_instruments_in_multiple_prices(
        )

        return list_of_instruments
Beispiel #28
0
def get_current_contract_price_series_for_instrument(data, instrument_code):
    diag_prices = diagPrices(data)
    price_series = diag_prices.get_current_priced_contract_prices_for_instrument(
        instrument_code)

    return price_series
def _roll_adjusted_and_multiple_prices(data, instrument_code):
    """
    Roll multiple and adjusted prices

    THE POSITION MUST BE ZERO IN THE PRICED CONTRACT! WE DON'T CHECK THIS HERE

    :param data: dataBlob
    :param instrument_code: str
    :return:
    """
    print(landing_strip(80))
    print("")
    print("Rolling adjusted prices!")
    print("")

    diag_prices = diagPrices(data)

    current_multiple_prices = diag_prices.get_multiple_prices(instrument_code)

    # Only required for potential rollback
    current_adjusted_prices = diag_prices.get_adjusted_prices(instrument_code)

    try:
        updated_multiple_prices = update_multiple_prices_on_roll(
            data, current_multiple_prices, instrument_code)
        new_adj_prices = futuresAdjustedPrices.stich_multiple_prices(
            updated_multiple_prices)
    except Exception as e:
        data.log.warn("%s : went wrong when rolling: No roll has happened" % e)
        return failure

    # We want user input before we do anything
    compare_old_and_new_prices([
        current_multiple_prices, updated_multiple_prices,
        current_adjusted_prices, new_adj_prices
    ], [
        "Current multiple prices", "New multiple prices",
        "Current adjusted prices", "New adjusted prices"
    ])
    print("")
    confirm_roll = input(
        "Confirm roll adjusted prices for %s are you sure y/n:" %
        instrument_code)
    if confirm_roll != "y":
        print(
            "\nUSER DID NOT WANT TO ROLL: Setting roll status back to previous state"
        )
        return failure

    try:
        # Apparently good let's try and write rolled data
        price_updater = updatePrices(data)
        price_updater.add_adjusted_prices(instrument_code,
                                          new_adj_prices,
                                          ignore_duplication=True)
        price_updater.add_multiple_prices(instrument_code,
                                          updated_multiple_prices,
                                          ignore_duplication=True)

    except Exception as e:
        data.log.warn(
            "%s went wrong when rolling: Going to roll-back to original multiple/adjusted prices"
            % e)
        rollback_adjustment(data, instrument_code, current_adjusted_prices,
                            current_multiple_prices)
        return failure

    return success