def get_factor_performance_attribution(portfolio_name, start_date, end_date, factor_ids, model_id=DEFAULT_MODEL_ID): oper = OpOperation(schema.Query) sim = oper.model(id=model_id).simulation( position_set=schema.PositionSetInput( id=get_portfolio_id(portfolio_name), type="PORTFOLIO"), from_=start_date, to=end_date, ) performance = sim.performance performance.date() performance.percent_return_cumulative.attribution.factors( id=factor_ids).__fields__("id", "value") results = oper() results df = pd.DataFrame(data=[ (p.date, f.id, f.value) for p in results.model.simulation.performance for f in p.percent_return_cumulative.attribution.factors ], columns=['date', 'id', 'value']) df.value = df.value + 1 df['daily_value'] = df.groupby('id')['value'].pct_change(1) df.value = df.value - 1 return df
def get_portfolio_performance( name, start_date, end_date, base=None, interval=schema.PositionSetInterval.AUTO, model_id=DEFAULT_MODEL_ID, ): summary_fields = ["trading", "factors", "specific"] factor_fields = ["id", "name", "category", "value"] if base is None: base = [] oper = OpOperation(schema.Query) model = oper.model(id=model_id) port = schema.PositionSetInput(id=get_portfolio_id(name), type="PORTFOLIO") model.simulation(position_set=port, from_=start_date, to=end_date, base=base, interval=interval).performance.__fields__("date") attr = oper.model.simulation.performance.percent_return_cumulative.attribution attr.summary.__fields__(*summary_fields) attr.factors.__fields__(*factor_fields) res = oper() df_summary = pd.DataFrame( data=[( p.date, *[ p.percent_return_cumulative.attribution.summary[f] for f in summary_fields ], ) for p in res.model.simulation.performance], columns=["date"] + summary_fields, ) # We're given cumulative values but may want daily values. df_summary["trading_daily"] = (1 + df_summary.trading).pct_change() df_summary.trading_daily.iat[0] = df_summary.trading[0] df_summary["factors_daily"] = (1 + df_summary.factors).pct_change() df_summary.factors_daily.iat[0] = df_summary.factors[0] df_summary["specific_daily"] = (1 + df_summary.specific).pct_change() df_summary.specific_daily.iat[0] = df_summary.specific[0] df_summary[ "total"] = df_summary.trading + df_summary.factors + df_summary.specific df_summary["total_daily"] = (1 + df_summary.total).pct_change() df_summary.total_daily.iat[0] = df_summary.total[0] factor_data = [] for p in res.model.simulation.performance: for pf in p.percent_return_cumulative.attribution.factors: factor_data.append([p.date] + [pf[f] for f in factor_fields]) df_factors = pd.DataFrame(data=factor_data, columns=["date"] + factor_fields) return df_summary, df_factors
def df_to_position_set(df: pd.DataFrame): dates = [] for dt in df.date.unique(): equities = [ schema.PositionSetEquityInput( id=schema.PositionSetEquityIdInput(sedol=row.sedol), economic_exposure=row.economic_exposure, ) for _, row in df[df.date == dt].iterrows() ] dates += [schema.PositionSetDateInput(equities=equities, date=dt)] return schema.PositionSetInput(dates=dates)
def get_performance_contributors(portfolio_name, start_date, end_date, model_id=DEFAULT_MODEL_ID): oper = OpOperation(schema.Query) sim = oper.model(id=model_id).simulation( position_set=schema.PositionSetInput( id=get_portfolio_id(portfolio_name), type="PORTFOLIO"), from_=start_date, to=end_date, ) sim.performance_contributors( equity_id_format="MODEL_PROVIDER_ID").__fields__( "id", "sedol", "average_percent_equity", "total") sim.performance_contributors.attribution.summary.__fields__( "factors", "specific", "trading") results = oper() values = [[ pc.sedol, pc.id, pc.average_percent_equity, pc.total, pc_at.factors, pc_at.specific, pc_at.trading, ] for pc in results.model.simulation.performance_contributors for pc_at in [pc.attribution.summary]] return pd.DataFrame( data=values, columns=[ "sedol", "model_provider_id", "average_percent_equity", "total", "factors", "specific", "trading", ], )
def get_exposure_contributors(portfolio_name, start_date, end_date, model_id=DEFAULT_MODEL_ID): oper = OpOperation(schema.Query) ec = oper.model(id=model_id).simulation( position_set=schema.PositionSetInput( id=get_portfolio_id(portfolio_name), type="PORTFOLIO"), from_=start_date, to=end_date, ) ec.exposure_contributors( equity_id_format="MODEL_PROVIDER_ID").__fields__("date") ec.exposure_contributors.contributors.__fields__("sedol", "id", "percent_equity") results = oper() values = [[ec_date.date, ec.sedol, ec.id, ec.percent_equity] for ec_date in results.model.simulation.exposure_contributors for ec in ec_date.contributors] return pd.DataFrame( data=values, columns=["date", "sedol", "model_provider_id", "percent_equity"])
def optimize_portfolio(portfolio_name, dt, objective, constraints, constants=schema.OptimizationConstantsInput(), forecast=None, model_id=DEFAULT_MODEL_ID): '''Optimize an uploaded portfolio''' pos_data = [] position_set = schema.PositionSetInput(id=get_portfolio_id(portfolio_name), type="PORTFOLIO") oper = OpOperation(schema.Query) if forecast is None: optimization = oper.model(id=model_id).optimization( position_set=position_set, objective=[objective], constants=constants, constraints=constraints, on=[dt]) else: optimization = oper.model(id=model_id).optimization( position_set=position_set, objective=[objective], constants=constants, constraints=constraints, on=[dt], forecast=forecast) opt_dates = optimization.positions().dates opt_dates.date() opt_dates.equities().id().model_provider_id() opt_dates.equities().__fields__("id", "economic_exposure") results = oper() pos_data += [[ pos_date.date, equity.id.model_provider_id, equity.economic_exposure ] for pos_date in results.model.optimization.positions.dates for equity in pos_date.equities] columns = ["date", "model_provider_id", "economic_exposure"] df_pos = pd.DataFrame(data=pos_data, columns=columns) return df_pos
def get_market_impact_date(mi_date, deltas, nav, denominator=None, model_id=DEFAULT_MODEL_ID): if denominator == None: denominator = nav equities = [ schema.PositionSetEquityInput( id=schema.PositionSetEquityIdInput(model_provider_id=id), economic_exposure=pct_equity * nav, ) for id, pct_equity in deltas.items() ] ps_delta = schema.PositionSetDateInput(date=mi_date, equities=equities) oper = OpOperation(schema.Query) market_impact = (oper.model(id=model_id).simulation( position_set=schema.PositionSetInput()).market_impact( position_set_delta=ps_delta, equity_id_format="MODEL_PROVIDER_ID", scale_format="DEFAULT", )) market_impact.cost() market_impact.contributors().__fields__("id", "cost") res = oper() total_cost = res.model.simulation.market_impact.cost total_cost_pct = total_cost / denominator df_total = pd.DataFrame( data=[[mi_date, total_cost, total_cost_pct]], columns=["date", "total_cost", "total_cost_pct"], ) contributors = [(mi_date, c.id, c.cost, c.cost / denominator) for c in res.model.simulation.market_impact.contributors] df_contrib = pd.DataFrame( data=contributors, columns=["date", "model_provider_id", "cost", "cost_pct"]) return df_total, df_contrib
def load_optimized_portfolio(df, portfolio_name, nav, forecast_horizon, objective, model_id=DEFAULT_MODEL_ID): if portfolio_name not in [p.name for p in op.get_portfolios()]: op.create_portfolio(portfolio_name) errors = [] for dt in df.date.unique(): rows = list(row for index, row in df[df.date == dt].iterrows()) oper = op.OpOperation(schema.Query) long_len = len([r for r in rows if r.expected_return > 0]) if long_len > 0: long_base = nav / long_len short_len = len([r for r in rows if r.expected_return <= 0]) if short_len > 0: short_base = -nav / short_len equities = [ schema.PositionSetEquityInput( id=schema.PositionSetEquityIdInput(sedol=row.sedol), economic_exposure=long_base if row.expected_return > 0 else short_base, ) for row in rows ] position_set_dates = [ schema.PositionSetDateInput(equities=equities, date=dt) ] position_set = schema.PositionSetInput(dates=position_set_dates) forecast_equities = [ schema.ForecastEquityInput( id=schema.PositionSetEquityIdInput(sedol=row.sedol), expected_percent_return=row.expected_return, ) for row in rows ] forecast = schema.ForecastInput(horizon=forecast_horizon, equities=forecast_equities) constants = schema.OptimizationConstantsInput(equity=nav) optimization = oper.model(id=model_id).optimization( position_set=position_set, objective=[objective], constants=constants, constraints=constraints, forecast=forecast, ) opt_dates = optimization.positions().dates opt_dates.date() opt_dates.equities().id().sedol() opt_dates.equities().__fields__("id", "economic_exposure") results = None try: results = oper() except op.GqlError as gql_err: errors.append((dt, gql_err)) values = [[pos_date.date, equity.id.sedol, equity.economic_exposure] for pos_date in results.model.optimization.positions.dates for equity in pos_date.equities] columns = ["date", "sedol", "economic_exposure"] df_pos = pd.DataFrame(data=values, columns=columns) upload_portfolio_positions(portfolio_name, df_pos, nav=nav) return errors