from io import StringIO
import pandas as pd
import qcs
from qcs import AllocationSnapshot, Constraint, Context, OptimizerConstraint
def print_snapshot(snapshot):
positions = [p.model_dump() for p in snapshot.positions]
df_positions = pd.DataFrame(positions)
df_positions = df_positions.set_index("ticker")
print(df_positions)
positions = [
{
"ticker": "EQUITYJPY8",
"size": 1.0,
"expected_return": 0.036706,
},
{
"ticker": "EQUITYEUR26",
"size": 1.0,
"expected_return": -0.029790,
},
{
"ticker": "EQUITYAUD31",
"size": 1.0,
"expected_return": 0.001753,
},
{
"ticker": "EQUITYGBP35",
"size": 1.0,
"expected_return": -0.069955,
},
]
snapshot = AllocationSnapshot(currency="EUR", positions=positions)
print("Original snapshot:")
print_snapshot(snapshot)
print("\n")
# Create context
assets_csv = """
CODE,LABEL,TYPE,CURRENCY,SCALE,ALIAS1,ALIAS2,ALIAS3,FORMULA,COUNTRY,SECTOR,SOURCE,RATING,OTHER,SHO,MCP,VOLUME,PER,EST,MATURITY,COUPON,LASTPRICE,HISTVOL,OTHERNUM,UNDER,VOLS,SPREADS,YCURVE,DDELINK,OTHERMAT,ISSUER,UNDERMAT,OTHER2,OTHER3,EXCHANGE,SUBSEC,EPS,BSCD,LDD,LDV,NFDD,NFDV,TMR,HISTORY,ISSUER_CODE,COUNTERPARTY,REGION,OPTIONTYPE,MULTIPLIER,EXERCISESTYLE,VOLATILITYVALUE,STRIKE,COUPONTYPE,LASTCOUPON,LASTCOUPONDATE,MARGIN,TENOR,RECOVERYRATE,FREQUENCY,MARKETPRICE,NOMINAL,CONVERSIONFACTOR,NOTIONAL1,NOTIONAL2,YIELDCURVE2,UNDERLYINGCOUPON,UNDERLYINGCURRENCY,UNDERLYINGFREQUENCY,UNDERLYING2,PRICETYPE,LASTVALUE,FORWARDVALUE,UNDERLYINGPRICE,OTHERCURRENCY,LIQUIDITY,BIDASK
<EQUITYJPY8>,<EquityJPY8>,EQU,JPY,,EquityJPY8,,,"RTHST([CODE],[LABEL],[CURRENCY],[HISTORY],'116',[OTHER])",JPN,Energy,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,EquityJPY8,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
<EQUITYEUR26>,<EquityEUR26>,EQU,EUR,,EquityEUR26,,,"RTHST([CODE],[LABEL],[CURRENCY],[HISTORY],'116',[OTHER])",DEU,Materials,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,EquityEUR26,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
<EQUITYAUD31>,<EquityAUD31>,EQU,AUD,,EquityAUD31,,,"RTHST([CODE],[LABEL],[CURRENCY],[HISTORY],'116',[OTHER])",AUS,Communication Services,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,EquityAUD31,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
<EQUITYGBP35>,<EquityGBP35>,EQU,GBP,,EquityGBP35,,,"RTHST([CODE],[LABEL],[CURRENCY],[HISTORY],'116',[OTHER])",JPN,Communication Services,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,EquityGBP35,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
"""
histories_csv = """
CODE,EQUITYAUD31,EQUITYEUR26,EQUITYGBP35,EQUITYJPY8
LABEL,EquityAUD31,EquityEUR26,EquityGBP35,EquityJPY8
CUR,AUD,EUR,GBP,JPY
TYPECODE,other,other,other,other
2019-11-07,3.0642,41.024,39.35,940.7
2019-12-01,3.3698,37.136,39.5,943.4
2020-01-01,3.0904,36.218,38.95,1018.9
2020-02-01,3.3523,33.335,41.87,923.9
2020-03-01,3.0625,30.137,34.15,836.4
2020-04-01,2.8571,23.487,20.98,528.4
2020-05-01,2.6696,26.808,27.92,603.8
2020-06-01,2.875,29.088,34.32,664.7
2020-07-01,2.8392,29.49,33.42,603.2
2020-08-01,2.991,29.748,32.16,546.7
2020-09-01,2.5946,36.094,37.42,607.9
2020-10-01,2.5671,38.43,31.74,514.2
2020-11-01,2.4571,37.09,31.94,449
2020-12-01,2.8238,43.11,45.76,529.3
2021-01-01,2.7321,45.7,45.64,518.2
2021-02-01,2.8971,52.435,44.14,560.1
2021-03-01,2.9613,55.604,53.85,739.1
2021-04-01,3.1963,51.874,49.76,711.1
2021-05-01,3.1869,50.385,49.01,695.3
2021-06-01,3.2715,53.959,48.76,719.5
2021-07-01,3.5348,51.367,47.3,796.6
2021-08-01,3.5536,50.237,49.5,739.3
2021-09-01,3.733,51.089,49.33,730.7
2021-10-01,3.7426,53.7,52.14,842.3
2021-11-01,3.7618,51.607,46.74,924.4
2021-12-01,3.8673,47.867,42.23,894.8
2022-01-01,4.0113,50.182,41.88,982.8
2022-02-01,3.781,49.515,41.58,1093.7
2022-03-01,3.8001,42.71,30.13,1198.6
2022-04-01,3.8491,42.275,28.63,1391.9
2022-05-01,3.9569,41.29,31.75,1502.7
2022-06-01,3.9177,43.08,28.54,1570.4
2022-07-01,3.761,32.53,18.585,1409
2022-08-01,3.8883,33.05,22.4,1506
2022-09-01,3.95,29.58,20.4,1557
2022-10-01,3.85,29.54,15.845,1359
2022-11-01,3.85,33.93,17.35,1545
"""
assets = qcs.import_assets_from_csv(StringIO(assets_csv))
histories = qcs.import_histories_from_csv(
StringIO(histories_csv), sep=",", date_format="%Y-%m-%d"
)
context = Context(
date="2022-11-28",
horizon="1m",
local_db={"assets": assets, "histories": histories},
)
# Create constraints
constraints = [
Constraint(
type="target",
value=1.0,
filter=lambda _asset: True,
label="Sum of weights = 1",
),
]
portfolio_constraints = snapshot.build_portfolio_constraints(
context, constraints
)
optimizer_constraints = [
OptimizerConstraint(constraint_type="std", target=0.25)
]
ef_result_dict = snapshot.efficient_frontier(
context=context,
optimizer_constraints=optimizer_constraints,
portfolio_constraints=portfolio_constraints,
cost_function="markowitz",
volatility_ladder=(0.20, 0.30, 0.05),
)
print(
pd.DataFrame(ef_result_dict["efficient_frontier"], columns=["vol", "perf"])
)