{"id":894,"date":"2026-05-12T15:05:02","date_gmt":"2026-05-12T07:05:02","guid":{"rendered":"https:\/\/connectword.dpdns.org\/?p=894"},"modified":"2026-05-12T15:05:02","modified_gmt":"2026-05-12T07:05:02","slug":"a-coding-implementation-to-portfolio-optimization-with-skfolio-for-building-testing-tuning-and-comparing-modern-investment-strategies","status":"publish","type":"post","link":"https:\/\/connectword.dpdns.org\/?p=894","title":{"rendered":"A Coding Implementation to Portfolio Optimization with skfolio for Building Testing, Tuning, and Comparing Modern Investment Strategies"},"content":{"rendered":"<p>In this tutorial, we explore <a href=\"https:\/\/github.com\/skfolio\/skfolio\"><strong>skfolio<\/strong><\/a>, a scikit-learn compatible portfolio optimization library that helps us build, compare, and evaluate different investment strategies in a structured Python workflow. We start by loading S&amp;P 500 price data, converting it into returns, and creating a time-based train-test split suitable for financial analysis. From there, we build simple baseline portfolios, test mean-variance optimization, compare alternative risk measures, apply risk-parity methods, and use hierarchical clustering techniques such as HRP and Nested Clusters Optimization. We also move into more advanced portfolio construction ideas, including robust covariance estimators, Black-Litterman views, factor models, pre-selection pipelines, walk-forward validation, and hyperparameter tuning with GridSearchCV.<\/p>\n<div class=\"dm-code-snippet dark dm-normal-version default no-background-mobile\">\n<div class=\"control-language\">\n<div class=\"dm-buttons\">\n<div class=\"dm-buttons-left\">\n<div class=\"dm-button-snippet red-button\"><\/div>\n<div class=\"dm-button-snippet orange-button\"><\/div>\n<div class=\"dm-button-snippet green-button\"><\/div>\n<\/div>\n<div class=\"dm-buttons-right\"><a><span class=\"dm-copy-text\">Copy Code<\/span><span class=\"dm-copy-confirmed\">Copied<\/span><span class=\"dm-error-message\">Use a different Browser<\/span><\/a><\/div>\n<\/div>\n<pre class=\" no-line-numbers\"><code class=\" no-wrap language-php\">import subprocess, sys\ndef _pip_install(pkg):\n   subprocess.check_call([sys.executable, \"-m\", \"pip\", \"install\", \"-q\", pkg])\n\n\ntry:\n   import skfolio  # noqa: F401\nexcept ImportError:\n   _pip_install(\"skfolio\")\n   import skfolio  # noqa: F401\n\n\nprint(f\"skfolio version: {skfolio.__version__}\")\n\n\nimport warnings\nwarnings.filterwarnings(\"ignore\")\n\n\nimport numpy as np\nimport pandas as pd\nimport plotly.io as pio\n\n\ntry:\n   pio.renderers.default = \"colab\"\nexcept Exception:\n   pio.renderers.default = \"notebook\"\n\n\nfrom sklearn import set_config\nfrom sklearn.model_selection import (\n   GridSearchCV, KFold, train_test_split,\n)\nfrom sklearn.pipeline import Pipeline\n\n\nfrom skfolio import RatioMeasure, RiskMeasure, Population\nfrom skfolio.datasets import load_factors_dataset, load_sp500_dataset\nfrom skfolio.preprocessing import prices_to_returns\nfrom skfolio.model_selection import WalkForward, cross_val_predict\n\n\nfrom skfolio.optimization import (\n   EqualWeighted, InverseVolatility, Random,\n   MeanRisk, ObjectiveFunction,\n   RiskBudgeting,\n   HierarchicalRiskParity,\n   NestedClustersOptimization,\n)\nfrom skfolio.moments import (\n   EmpiricalCovariance, LedoitWolf, DenoiseCovariance, GerberCovariance,\n   EmpiricalMu, EWMu, ShrunkMu,\n)\nfrom skfolio.prior import EmpiricalPrior, BlackLitterman, FactorModel\nfrom skfolio.pre_selection import SelectKExtremes\n\n\nset_config(transform_output=\"pandas\")\n\n\nprices = load_sp500_dataset()\nprint(\"Prices shape:\", prices.shape)\nprint(prices.tail(3))\n\n\nX = prices_to_returns(prices)\nprint(\"nReturns shape:\", X.shape)\n\n\nX_train, X_test = train_test_split(X, test_size=0.33, shuffle=False)\nprint(f\"Train: {X_train.index.min().date()} \u2192 {X_train.index.max().date()}  ({len(X_train)} days)\")\nprint(f\"Test : {X_test.index.min().date()} \u2192 {X_test.index.max().date()}  ({len(X_test)} days)\")<\/code><\/pre>\n<\/div>\n<\/div>\n<p>We install and import all the required libraries, including skfolio, scikit-learn, pandas, NumPy, and Plotly. We load the S&amp;P 500 dataset, convert asset prices into returns, and prepare the data for portfolio optimization. We split the returns into training and test sets in chronological order to avoid look-ahead bias.<\/p>\n<div class=\"dm-code-snippet dark dm-normal-version default no-background-mobile\">\n<div class=\"control-language\">\n<div class=\"dm-buttons\">\n<div class=\"dm-buttons-left\">\n<div class=\"dm-button-snippet red-button\"><\/div>\n<div class=\"dm-button-snippet orange-button\"><\/div>\n<div class=\"dm-button-snippet green-button\"><\/div>\n<\/div>\n<div class=\"dm-buttons-right\"><a><span class=\"dm-copy-text\">Copy Code<\/span><span class=\"dm-copy-confirmed\">Copied<\/span><span class=\"dm-error-message\">Use a different Browser<\/span><\/a><\/div>\n<\/div>\n<pre class=\" no-line-numbers\"><code class=\" no-wrap language-php\">benchmarks = {\n   \"1\/N (EqualWeighted)\": EqualWeighted(),\n   \"Inverse-Volatility\":  InverseVolatility(),\n   \"Random (Dirichlet)\":  Random(),\n}\n\n\nbaseline_population = Population([])\nfor name, mdl in benchmarks.items():\n   mdl.fit(X_train)\n   ptf = mdl.predict(X_test)\n   ptf.name = name\n   baseline_population.append(ptf)\n   print(f\"{name:25s}  Sharpe={ptf.annualized_sharpe_ratio:.3f}  \"\n         f\"AnnRet={ptf.annualized_mean:.3%}  AnnVol={ptf.annualized_standard_deviation:.3%}\")\n\n\nmin_var = MeanRisk(risk_measure=RiskMeasure.VARIANCE)\nmin_var.fit(X_train)\nprint(\"nMin-Variance weights (top 5):\")\nprint(pd.Series(min_var.weights_, index=X_train.columns).sort_values(ascending=False).head())\n\n\nptf_min_var = min_var.predict(X_test)\nptf_min_var.name = \"Min Variance\"\n\n\nmax_sharpe = MeanRisk(\n   objective_function=ObjectiveFunction.MAXIMIZE_RATIO,\n   risk_measure=RiskMeasure.VARIANCE,\n)\nmax_sharpe.fit(X_train)\nptf_max_sharpe = max_sharpe.predict(X_test)\nptf_max_sharpe.name = \"Max Sharpe\"\n\n\nef = MeanRisk(\n   risk_measure=RiskMeasure.VARIANCE,\n   efficient_frontier_size=20,\n   portfolio_params=dict(name=\"EF\"),\n)\nef.fit(X_train)\nef_population_test = ef.predict(X_test)\nprint(f\"nEfficient frontier produced {len(ef_population_test)} portfolios.\")\n\n\nfig = ef_population_test.plot_measures(\n   x=RiskMeasure.ANNUALIZED_VARIANCE,\n   y=RatioMeasure.ANNUALIZED_SHARPE_RATIO,\n)\nfig.show()<\/code><\/pre>\n<\/div>\n<\/div>\n<p>We create simple benchmark portfolios using equal weighting, inverse volatility, and random allocation. We then build mean-variance portfolios, including minimum-variance and maximum Sharpe-ratio strategies. We also generate an efficient frontier and visualize the trade-off between portfolio risk and performance.<\/p>\n<div class=\"dm-code-snippet dark dm-normal-version default no-background-mobile\">\n<div class=\"control-language\">\n<div class=\"dm-buttons\">\n<div class=\"dm-buttons-left\">\n<div class=\"dm-button-snippet red-button\"><\/div>\n<div class=\"dm-button-snippet orange-button\"><\/div>\n<div class=\"dm-button-snippet green-button\"><\/div>\n<\/div>\n<div class=\"dm-buttons-right\"><a><span class=\"dm-copy-text\">Copy Code<\/span><span class=\"dm-copy-confirmed\">Copied<\/span><span class=\"dm-error-message\">Use a different Browser<\/span><\/a><\/div>\n<\/div>\n<pre class=\" no-line-numbers\"><code class=\" no-wrap language-php\">risk_measures = {\n   \"Min CVaR-95\":         RiskMeasure.CVAR,\n   \"Min Semi-Variance\":   RiskMeasure.SEMI_VARIANCE,\n   \"Min CDaR\":            RiskMeasure.CDAR,\n   \"Min Max Drawdown\":    RiskMeasure.MAX_DRAWDOWN,\n}\n\n\nrisk_pop = Population([ptf_min_var, ptf_max_sharpe])\nfor name, rm in risk_measures.items():\n   m = MeanRisk(risk_measure=rm)\n   m.fit(X_train)\n   p = m.predict(X_test)\n   p.name = name\n   risk_pop.append(p)\n\n\nprint(\"nRisk-measure comparison on test set:\")\n_summary = risk_pop.summary()\n_wanted = [\"Annualized Sharpe Ratio\", \"Annualized Sortino Ratio\",\n          \"CVaR at 95%\", \"Maximum Drawdown\", \"Max Drawdown\"]\n_have = [r for r in _wanted if r in _summary.index]\nprint(_summary.loc[_have].T)\n\n\nrb_var  = RiskBudgeting(risk_measure=RiskMeasure.VARIANCE)\nrb_cvar = RiskBudgeting(risk_measure=RiskMeasure.CVAR)\nrb_var.fit(X_train);   rb_cvar.fit(X_train)\nptf_rb_var  = rb_var.predict(X_test);   ptf_rb_var.name  = \"Risk Parity (Var)\"\nptf_rb_cvar = rb_cvar.predict(X_test);  ptf_rb_cvar.name = \"Risk Parity (CVaR)\"\n\n\nhrp = HierarchicalRiskParity(risk_measure=RiskMeasure.VARIANCE)\nhrp.fit(X_train)\nptf_hrp = hrp.predict(X_test); ptf_hrp.name = \"HRP\"\n\n\nnco = NestedClustersOptimization(\n   inner_estimator=MeanRisk(risk_measure=RiskMeasure.CVAR),\n   outer_estimator=RiskBudgeting(risk_measure=RiskMeasure.VARIANCE),\n   cv=KFold(n_splits=5),\n   n_jobs=-1,\n)\nnco.fit(X_train)\nptf_nco = nco.predict(X_test); ptf_nco.name = \"Nested Clusters\"\n\n\nhrp.hierarchical_clustering_estimator_.plot_dendrogram().show()<\/code><\/pre>\n<\/div>\n<\/div>\n<p>We compare different risk measures, including CVaR, semi-variance, CDaR, and maximum drawdown. We build risk-budgeting portfolios to more evenly distribute risk contributions across assets. We also apply hierarchical methods, such as HRP and Nested Clusters Optimization, to capture asset relationships through clustering.<\/p>\n<div class=\"dm-code-snippet dark dm-normal-version default no-background-mobile\">\n<div class=\"control-language\">\n<div class=\"dm-buttons\">\n<div class=\"dm-buttons-left\">\n<div class=\"dm-button-snippet red-button\"><\/div>\n<div class=\"dm-button-snippet orange-button\"><\/div>\n<div class=\"dm-button-snippet green-button\"><\/div>\n<\/div>\n<div class=\"dm-buttons-right\"><a><span class=\"dm-copy-text\">Copy Code<\/span><span class=\"dm-copy-confirmed\">Copied<\/span><span class=\"dm-error-message\">Use a different Browser<\/span><\/a><\/div>\n<\/div>\n<pre class=\" no-line-numbers\"><code class=\" no-wrap language-php\">robust = MeanRisk(\n   objective_function=ObjectiveFunction.MAXIMIZE_RATIO,\n   risk_measure=RiskMeasure.VARIANCE,\n   prior_estimator=EmpiricalPrior(\n       mu_estimator=ShrunkMu(),\n       covariance_estimator=DenoiseCovariance(),\n   ),\n)\nrobust.fit(X_train)\nptf_robust = robust.predict(X_test); ptf_robust.name = \"Max Sharpe (Robust)\"\n\n\ngerber = MeanRisk(\n   risk_measure=RiskMeasure.VARIANCE,\n   prior_estimator=EmpiricalPrior(covariance_estimator=GerberCovariance()),\n)\ngerber.fit(X_train)\nptf_gerber = gerber.predict(X_test); ptf_gerber.name = \"Min Var (Gerber)\"\n\n\nassets = list(X_train.columns)\n\n\ngroup_a = assets[:10]; group_b = assets[10:]\ngroups = pd.DataFrame(\n   {a: [\"GroupA\" if a in group_a else \"GroupB\"] for a in assets},\n   index=[\"Sector\"],\n)\n\n\nconstrained = MeanRisk(\n   objective_function=ObjectiveFunction.MAXIMIZE_RATIO,\n   risk_measure=RiskMeasure.VARIANCE,\n   min_weights=0.0,\n   max_weights=0.20,\n   transaction_costs=0.0005,\n   groups=groups,\n   linear_constraints=[\n       \"GroupA &lt;= 0.6\",\n       \"GroupB &gt;= 0.2\",\n   ],\n   l2_coef=0.01,\n)\nconstrained.fit(X_train)\nptf_constr = constrained.predict(X_test); ptf_constr.name = \"Constrained MV\"\nprint(\"nConstrained portfolio weights:\")\nprint(pd.Series(constrained.weights_, index=assets).round(4))\n\n\nprint(\"nAvailable tickers:\", list(X_train.columns))\n\n\nbl_views = [\n   \"AAPL == 0.0008\",\n   \"JPM - BAC == 0.0002\",\n]\nbl = MeanRisk(\n   objective_function=ObjectiveFunction.MAXIMIZE_RATIO,\n   risk_measure=RiskMeasure.VARIANCE,\n   prior_estimator=BlackLitterman(views=bl_views),\n)\nbl.fit(X_train)\nptf_bl = bl.predict(X_test); ptf_bl.name = \"Black-Litterman\"<\/code><\/pre>\n<\/div>\n<\/div>\n<p>We improve portfolio stability by using robust estimators such as shrunk mean, denoised covariance, and Gerber covariance. We add real-world constraints like maximum asset weights, group limits, transaction costs, and L2 regularization. We also apply Black-Litterman views to combine market-based assumptions with our own return expectations.<\/p>\n<div class=\"dm-code-snippet dark dm-normal-version default no-background-mobile\">\n<div class=\"control-language\">\n<div class=\"dm-buttons\">\n<div class=\"dm-buttons-left\">\n<div class=\"dm-button-snippet red-button\"><\/div>\n<div class=\"dm-button-snippet orange-button\"><\/div>\n<div class=\"dm-button-snippet green-button\"><\/div>\n<\/div>\n<div class=\"dm-buttons-right\"><a><span class=\"dm-copy-text\">Copy Code<\/span><span class=\"dm-copy-confirmed\">Copied<\/span><span class=\"dm-error-message\">Use a different Browser<\/span><\/a><\/div>\n<\/div>\n<pre class=\" no-line-numbers\"><code class=\" no-wrap language-php\">factor_prices = load_factors_dataset()\nX_full, F_full = prices_to_returns(prices, factor_prices)\n\n\nX_tr, X_te, F_tr, F_te = train_test_split(\n   X_full, F_full, test_size=0.33, shuffle=False\n)\n\n\nfm = MeanRisk(\n   objective_function=ObjectiveFunction.MAXIMIZE_RATIO,\n   risk_measure=RiskMeasure.VARIANCE,\n   prior_estimator=FactorModel(),\n)\nfm.fit(X_tr, F_tr)\nptf_fm = fm.predict(X_te); ptf_fm.name = \"Factor Model\"\nprint(f\"nFactor-model Sharpe: {ptf_fm.annualized_sharpe_ratio:.3f}\")\n\n\npipe = Pipeline([\n   (\"preselect\",   SelectKExtremes(k=8, highest=True)),\n   (\"optimize\",    MeanRisk(\n       objective_function=ObjectiveFunction.MAXIMIZE_RATIO,\n       risk_measure=RiskMeasure.VARIANCE)),\n])\npipe.fit(X_train)\nptf_pipe = pipe.predict(X_test); ptf_pipe.name = \"Top-8 + Max Sharpe\"\n\n\nwf_model = MeanRisk(\n   objective_function=ObjectiveFunction.MAXIMIZE_RATIO,\n   risk_measure=RiskMeasure.VARIANCE,\n)\nmp_portfolio = cross_val_predict(\n   wf_model, X,\n   cv=WalkForward(train_size=252*2, test_size=63),\n   n_jobs=-1,\n)\nmp_portfolio.name = \"Walk-Forward Max Sharpe\"\nprint(f\"nWalk-forward portfolio  Sharpe={mp_portfolio.annualized_sharpe_ratio:.3f}  \"\n     f\"CalmarRatio={mp_portfolio.calmar_ratio:.3f}\")\nmp_portfolio.plot_cumulative_returns().show()\n\n\ntuned = MeanRisk(\n   objective_function=ObjectiveFunction.MAXIMIZE_RATIO,\n   risk_measure=RiskMeasure.VARIANCE,\n   prior_estimator=EmpiricalPrior(mu_estimator=EWMu(alpha=0.1)),\n)\ngrid = GridSearchCV(\n   estimator=tuned,\n   cv=WalkForward(train_size=252*2, test_size=63),\n   n_jobs=-1,\n   param_grid={\n       \"l2_coef\": [0.0, 0.01, 0.1],\n       \"prior_estimator__mu_estimator__alpha\": [0.05, 0.1, 0.2, 0.5],\n   },\n)\ngrid.fit(X_train)\nprint(\"nBest params:\", grid.best_params_)\nprint(f\"Best CV score (Sharpe): {grid.best_score_:.3f}\")\n\n\nptf_tuned = grid.best_estimator_.predict(X_test); ptf_tuned.name = \"Tuned Max Sharpe\"\n\n\nfinal = Population([\n   *baseline_population,\n   ptf_min_var, ptf_max_sharpe,\n   ptf_rb_var, ptf_rb_cvar,\n   ptf_hrp, ptf_nco,\n   ptf_robust, ptf_gerber,\n   ptf_constr, ptf_bl, ptf_fm,\n   ptf_pipe, ptf_tuned,\n])\n\n\n_full = final.summary()\n_wanted_final = [\n   \"Annualized Mean\", \"Annualized Standard Deviation\",\n   \"Annualized Sharpe Ratio\", \"Annualized Sortino Ratio\",\n   \"CVaR at 95%\", \"Maximum Drawdown\", \"Max Drawdown\",\n]\n_have_final = [r for r in _wanted_final if r in _full.index]\nsummary = _full.loc[_have_final].T.sort_values(\n   \"Annualized Sharpe Ratio\", ascending=False\n)\n\n\nprint(\"n\" + \"=\" * 80)\nprint(\"FINAL HORSE RACE \u2014 sorted by Sharpe (out-of-sample test set)\")\nprint(\"=\" * 80)\nprint(summary.to_string())\n\n\nfinal.plot_cumulative_returns().show()\n\n\nfinal.plot_composition().show()\n\n\nptf_rb_var.plot_contribution(measure=RiskMeasure.VARIANCE).show()\n\n\nprint(\"nDone. Try swapping risk measures, adding constraints, or wiring in\")\nprint(\"your own returns DataFrame \u2014 every estimator follows the sklearn API.\")<\/code><\/pre>\n<\/div>\n<\/div>\n<p>We build a factor model to explain asset returns using external factor data and optimize based on that structure. We create a pre-selection pipeline, run walk-forward validation, and tune hyperparameters using GridSearchCV. We finally compare all portfolio strategies in a single horse race using summary metrics, cumulative returns, composition, and risk-contribution plots.<\/p>\n<p>In conclusion, we completed a full portfolio optimization workflow using Skfolio, moving from basic benchmark strategies to advanced model-driven portfolio construction techniques. We compared equal-weighted, inverse-volatility, mean-variance, risk-parity, hierarchical, robust, constrained, Black-Litterman, factor-based, and tuned portfolios on an out-of-sample test set. By using skfolio\u2019s scikit-learn style API, we kept the workflow modular, readable, and easy to extend with new constraints, risk measures, estimators, or custom return data.<\/p>\n<hr class=\"wp-block-separator has-alpha-channel-opacity\" \/>\n<p>Check out\u00a0the\u00a0<strong><a href=\"https:\/\/github.com\/Marktechpost\/AI-Agents-Projects-Tutorials\/blob\/main\/Data%20Science\/portfolio_optimization_with_skfolio_Marktechpost.ipynb\" target=\"_blank\" rel=\"noreferrer noopener\">Full Codes here<\/a>.\u00a0<\/strong>Also,\u00a0feel free to follow us on\u00a0<strong><a href=\"https:\/\/x.com\/intent\/follow?screen_name=marktechpost\" target=\"_blank\" rel=\"noreferrer noopener\"><mark>Twitter<\/mark><\/a><\/strong>\u00a0and don\u2019t forget to join our\u00a0<strong><a href=\"https:\/\/www.reddit.com\/r\/machinelearningnews\/\" target=\"_blank\" rel=\"noreferrer noopener\">150k+ ML SubReddit<\/a><\/strong>\u00a0and Subscribe to\u00a0<strong><a href=\"https:\/\/www.aidevsignals.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">our Newsletter<\/a><\/strong>. Wait! are you on telegram?\u00a0<strong><a href=\"https:\/\/t.me\/machinelearningresearchnews\" target=\"_blank\" rel=\"noreferrer noopener\">now you can join us on telegram as well.<\/a><\/strong><\/p>\n<p>Need to partner with us for promoting your GitHub Repo OR Hugging Face Page OR Product Release OR Webinar etc.?\u00a0<strong><a href=\"https:\/\/forms.gle\/MTNLpmJtsFA3VRVd9\" target=\"_blank\" rel=\"noreferrer noopener\"><mark>Connect with us<\/mark><\/a><\/strong><\/p>\n<p>The post <a href=\"https:\/\/www.marktechpost.com\/2026\/05\/12\/a-coding-implementation-to-portfolio-optimization-with-skfolio-for-building-testing-tuning-and-comparing-modern-investment-strategies\/\">A Coding Implementation to Portfolio Optimization with skfolio for Building Testing, Tuning, and Comparing Modern Investment Strategies<\/a> appeared first on <a href=\"https:\/\/www.marktechpost.com\/\">MarkTechPost<\/a>.<\/p>","protected":false},"excerpt":{"rendered":"<p>In this tutorial, we explore s&hellip;<\/p>\n","protected":false},"author":1,"featured_media":29,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-894","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/connectword.dpdns.org\/index.php?rest_route=\/wp\/v2\/posts\/894","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/connectword.dpdns.org\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/connectword.dpdns.org\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/connectword.dpdns.org\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/connectword.dpdns.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=894"}],"version-history":[{"count":0,"href":"https:\/\/connectword.dpdns.org\/index.php?rest_route=\/wp\/v2\/posts\/894\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/connectword.dpdns.org\/index.php?rest_route=\/wp\/v2\/media\/29"}],"wp:attachment":[{"href":"https:\/\/connectword.dpdns.org\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=894"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/connectword.dpdns.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=894"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/connectword.dpdns.org\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=894"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}