def calc_delta_with_decays(row, risk_pd, risk_pids): pid = row['positionId'] result = row['deltaWithDecays'] if pid in risk_pids: result = [get_val(risk_pd.loc[pid]['deltas'], 0) / get_val(row['underlyerMultipliers'], 0), get_val(risk_pd.loc[pid]['deltas'], 1) / get_val(row['underlyerMultipliers'], 1)] return [np.nan, np.nan] if is_nan(result) else result
def process_positions(positions): multi_asset_position_criteria = positions.productType.isin(['RATIO_SPREAD_EUROPEAN', 'SPREAD_EUROPEAN']) single_asset_positions = positions[~multi_asset_position_criteria] multi_asset_positions = positions[multi_asset_position_criteria] if not multi_asset_positions.empty: multi_asset_rows = list() for index, row in multi_asset_positions.iterrows(): row2 = row.copy() row['underlyerPrice'] = get_val(row.get('underlyerPrices'), 0) row2['underlyerPrice'] = get_val(row.get('underlyerPrices'), 1) row['underlyerInstrumentId'] = get_val(row.get('underlyerInstrumentIds'), 0) row2['underlyerInstrumentId'] = get_val(row.get('underlyerInstrumentIds'), 1) multi_asset_rows.append(row) multi_asset_rows.append(row2) multi_asset_positions = pd.DataFrame(multi_asset_rows) single_asset_positions = pd.concat([multi_asset_positions, single_asset_positions], sort=False) return single_asset_positions
def process_multi_asset_pos(positions, cash_flows, risks, domain, headers, params): all_data = positions.merge(cash_flows, on='positionId', how='left').merge(risks, on='positionId', how='left') rpt = all_data[['positionId', 'bookName', 'counterPartyName', 'tradeId', 'asset.underlyerInstrumentId1', 'vegas', 'asset.underlyerInstrumentId2', 'productType', 'initialNumber1', 'initialNumber2', 'gammas', 'r', 'unwindNumber1', 'unwindNumber2', 'tradeDate', 'asset.expirationDate', 'message', 'deltas', 'qs', 'asset.underlyerMultiplier1', 'asset.underlyerMultiplier2', 'price', 'theta', 'settle', 'vols', 'quantity1', 'quantity2', 'actualPremium', 'open', 'underlyerPrices', 'rhoR', 'unwind']] rpt.rename(columns={'counterPartyName': 'partyName', 'asset.expirationDate': 'expirationDate'}, inplace=True) rpt['marketValue'] = rpt['price'] rpt['underlyerInstrumentIds'] = rpt.apply( lambda r: [r['asset.underlyerInstrumentId1'], r['asset.underlyerInstrumentId2']], axis=1) # TODO: 这种写法可能会有性能问题,但考虑到只是针对多资产交易,数量少,暂时这样做。若以后交易量大,后台应提供相应批量查询接口以避免频繁调用接口 rpt['correlation'] = rpt.apply(lambda r: get_correlation(r['underlyerInstrumentIds'], domain, headers), axis=1) rpt['underlyerMultipliers'] = rpt.apply( lambda r: [r['asset.underlyerMultiplier1'], r['asset.underlyerMultiplier2']], axis=1) rpt['initialNumbers'] = rpt.apply(lambda r: [r['initialNumber1'], r['initialNumber2']], axis=1) rpt['unwindNumbers'] = rpt.apply(lambda r: [r['unwindNumber1'], r['unwindNumber2']], axis=1) rpt['numbers'] = rpt.apply(lambda row: [np.float64(row['quantity1']) / row['underlyerMultipliers'][0], np.float64(row['quantity2']) / row['underlyerMultipliers'][1]], axis=1) rpt['premium'] = rpt.apply( lambda row: np.float64(row['actualPremium']) if is_nan(row['open']) else np.float64(row['open']), axis=1) rpt['unwindAmount'] = rpt.apply( lambda row: 0 if is_nan(row['open']) else np.float64(row['unwind']) + np.float64(row['settle']), axis=1) rpt['pnl'] = np.float64(rpt['marketValue']) + rpt['premium'] + rpt['unwindAmount'] rpt['deltas'] = rpt.apply(lambda r: [get_val(r['deltas'], 0) / get_val(r['underlyerMultipliers'], 0), get_val(r['deltas'], 1) / get_val(r['underlyerMultipliers'], 1)], axis=1) rpt['deltaCashes'] = rpt.apply(lambda r: [np.float64(r['deltas'][0]) * get_val(r['underlyerPrices'], 0), np.float64(r['deltas'][1]) * get_val(r['underlyerPrices'], 1)], axis=1) rpt['gammas'] = rpt.apply( lambda r: [get_val(r['gammas'], 0, 0) * get_val(r['underlyerPrices'], 0) / r['underlyerMultipliers'][0] / 100, get_val(r['gammas'], 1, 1) * get_val(r['underlyerPrices'], 1) / r['underlyerMultipliers'][1] / 100], axis=1) rpt['gammaCashes'] = rpt.apply(lambda r: [np.float64(r['gammas'][0]) * get_val(r['underlyerPrices'], 0), np.float64(r['gammas'][1]) * get_val(r['underlyerPrices'], 1)], axis=1) rpt['vegas'] = rpt.apply(lambda r: [get_val(r['vegas'], 0) / 100, get_val(r['vegas'], 1) / 100], axis=1) rpt['theta'] = np.float64(rpt['theta']) / 365 rpt['rho'] = np.float64(rpt['rhoR']) / 100 rpt['deltaDecays'] = np.nan rpt['deltaWithDecays'] = np.nan rpt.drop(['asset.underlyerInstrumentId1', 'asset.underlyerInstrumentId2', 'asset.underlyerMultiplier1', 'quantity1', 'asset.underlyerMultiplier2', 'initialNumber1', 'initialNumber2', 'rhoR', 'quantity2', 'actualPremium', 'open', 'settle', 'unwindNumber1', 'unwindNumber2', 'underlyerPrices', 'unwind'], axis=1, inplace=True) params['tradeIds'] = list(rpt.tradeId.unique()) decay_data = call_request(domain, 'pricing-service', 'prcPrice', params, headers) if 'result' in decay_data: diagnostics_pd = pd.DataFrame(decay_data['diagnostics']) if not diagnostics_pd.empty: diagnostics_pids = list(diagnostics_pd.key.unique()) diagnostics_pd.set_index('key', inplace=True) diagnostics_pd.drop_duplicates(inplace=True) rpt['message'] = rpt.apply(lambda row: get_error_msg(row, diagnostics_pd, diagnostics_pids), axis=1) risk_pd = pd.DataFrame(decay_data['result']) if not risk_pd.empty: risk_pids = list(risk_pd.positionId.unique()) risk_pd = risk_pd.set_index('positionId') rpt['deltaWithDecays'] = rpt.apply(lambda row: calc_delta_with_decays(row, risk_pd, risk_pids), axis=1) rpt['deltaDecays'] = rpt.apply(lambda r: [get_val(r['deltaWithDecays'], 0) - get_val(r['deltas'], 0), get_val(r['deltaWithDecays'], 1) - get_val(r['deltas'], 1)], axis=1) rpt['listedOption'] = False return rpt
def massage_data(risks, yst_positions, cash_flows_today, position_index): spread_types = ['RATIO_SPREAD_EUROPEAN', 'SPREAD_EUROPEAN'] if not position_index.empty: multi_asset_pid_criteria = position_index.productType.isin( spread_types) multi_asset_pids = position_index[multi_asset_pid_criteria] position_index = position_index[~multi_asset_pid_criteria] if not multi_asset_pids.empty: multi_asset_rows = list() multi_asset_pids.reset_index(inplace=True) multi_asset_position_ids = list( multi_asset_pids.positionId.unique()) for index, row in multi_asset_pids.iterrows(): row2 = row.copy() row['positionId'] = row['positionId'] + '_1' row2['positionId'] = row2['positionId'] + '_2' row['asset.underlyerInstrumentId'] = row[ 'asset.underlyerInstrumentId1'] row2['asset.underlyerInstrumentId'] = row[ 'asset.underlyerInstrumentId2'] row['asset.underlyerMultiplier'] = row[ 'asset.underlyerMultiplier1'] row2['asset.underlyerMultiplier'] = row[ 'asset.underlyerMultiplier2'] multi_asset_rows.append(row) multi_asset_rows.append(row2) multi_asset_pids = pd.DataFrame(multi_asset_rows).set_index( 'positionId') position_index = pd.concat([position_index, multi_asset_pids], sort=False) if not risks.empty: multi_asset_risks_criteria = risks.index.isin( multi_asset_position_ids) multi_asset_risks = risks[multi_asset_risks_criteria] risks = risks[~multi_asset_risks_criteria] if not multi_asset_risks.empty: multi_asset_rows = list() multi_asset_risks.reset_index(inplace=True) for index, row in multi_asset_risks.iterrows(): row2 = row.copy() row['positionId'] = row['positionId'] + '_1' row2['positionId'] = row2['positionId'] + '_2' row['vol'] = get_val(row.get('vols'), 0) row2['vol'] = get_val(row.get('vols'), 1) row['underlyerPrice'] = get_val( row.get('underlyerPrices'), 0) row2['underlyerPrice'] = get_val( row.get('underlyerPrices'), 1) multi_asset_rows.append(row) multi_asset_rows.append(row2) multi_asset_risks = pd.DataFrame( multi_asset_rows).set_index('positionId') risks = pd.concat([risks, multi_asset_risks], sort=False) if not cash_flows_today.empty: multi_asset_cash_flow_criteria = cash_flows_today.positionId.isin( multi_asset_position_ids) multi_asset_cash_flow = cash_flows_today[ multi_asset_cash_flow_criteria] cash_flows_today = cash_flows_today[ ~multi_asset_cash_flow_criteria] if not multi_asset_cash_flow.empty: multi_asset_rows = list() for index, row in multi_asset_cash_flow.iterrows(): row2 = row.copy() row['positionId'] = row['positionId'] + '_1' row2['positionId'] = row2['positionId'] + '_2' multi_asset_rows.append(row) multi_asset_rows.append(row2) multi_asset_cash_flow = pd.DataFrame(multi_asset_rows) cash_flows_today = pd.concat( [cash_flows_today, multi_asset_cash_flow], sort=False) if not yst_positions.empty: multi_asset_position_criteria = yst_positions.productType.isin( spread_types) multi_asset_positions = yst_positions[multi_asset_position_criteria] yst_positions = yst_positions[~multi_asset_position_criteria] if not multi_asset_positions.empty: multi_asset_rows = list() for index, row in multi_asset_positions.iterrows(): row2 = row.copy() row['positionId'] = row['positionId'] + '_1' row2['positionId'] = row2['positionId'] + '_2' row['vol'] = get_val(row.get('vols'), 0) row2['vol'] = get_val(row.get('vols'), 1) row['delta'] = get_val(row.get('deltas'), 0) row2['delta'] = get_val(row.get('deltas'), 1) row['gamma'] = get_val(row.get('gammas'), 0) row2['gamma'] = get_val(row.get('gammas'), 1) row['vega'] = get_val(row.get('vegas'), 0) row2['vega'] = get_val(row.get('vegas'), 1) row['number'] = get_val(row.get('numbers'), 0) row2['number'] = get_val(row.get('numbers'), 1) row['underlyerPrice'] = get_val(row.get('underlyerPrices'), 0) row2['underlyerPrice'] = get_val(row.get('underlyerPrices'), 1) row['underlyerInstrumentId'] = get_val( row.get('underlyerInstrumentIds'), 0) row2['underlyerInstrumentId'] = get_val( row.get('underlyerInstrumentIds'), 1) row['underlyerMultiplier'] = get_val( row.get('underlyerMultipliers'), 0) row2['underlyerMultiplier'] = get_val( row.get('underlyerMultipliers'), 1) multi_asset_rows.append(row) multi_asset_rows.append(row2) multi_asset_positions = pd.DataFrame(multi_asset_rows) yst_positions = pd.concat([yst_positions, multi_asset_positions], sort=False) return risks, yst_positions, cash_flows_today, position_index