← All insights

Article

Portfolio123 Claude Skill 4.1.1: Factor Recipes, a Current API and Fewer Wrong Answers

A terminal window with P123 SKILL in orange block letters, welcoming the v4.1.1 release and listing factor-replication.md with 35 recipes, api.md with 39 operations, p123api 3.1.0 with 44 methods and regional universe IDs verified live

The version of this skill we released in June recommended a low-volatility factor that returns NA for almost every stock. It didn’t misspell anything. BetaFunc(52, 104) is a real function with real arguments, but it asks for 104 samples of 52-bar returns, about twenty years of history, and since min_samples defaults to all of them, hardly any stock qualifies.

That’s the kind of mistake version 4.1.1 goes after. Version 3.0.0 gave Claude the full Portfolio123 dictionary, checked name by name, so it would stop inventing names. This release goes after the quieter errors, mostly ones where every name is real and the answer is still wrong. The dictionary underneath, 4,463 factors and 465 functions, is unchanged.

Download portfolio123.skill v4.1.1 from GitHub

What live use turned up

A practitioner running v3.0.0 against live Portfolio123 work reported four defects. We fixed them in 4.0.0, which was finished in July but held back until 17 September, when it went up on GitHub together with 4.1.0 and 4.1.1. The first is easy to replay. Say you ask Claude for the square root of a factor. Version 3’s guidance pointed only to Pow(number, power) (the ^ operator sat in a single operator table), so the skill produced Pow(x, 0.5) and, worse, invented Sqrt(x). Portfolio123 has no square-root and no exponential function: a root is x^0.5, and ^ is now the documented idiom, precedence included.

The other three were subtler:

  • SetVar and ShowVar return TRUE, never the assigned value. So Eval(SetVar(@x, f), A, NA) is true for every stock, and its NA branch is dead code.
  • Weight="0" on a ranking-system node is legal and means equal weight. Version 3 flagged valid systems as broken and rewrote them.
  • The p123api upload methods take snake_case keywords such as contains_header_row, not the camelCase query names, so headerRow=True raises a TypeError.

Later checks turned up more. The 12-1 momentum label sat on Ret%Chg(252, 21), which spans thirteen months; the eleven-month formation window is Ret%Chg(231, 21). And four files extended the free-trial data waiver beyond POST /data, the only operation the spec grants it on, so if you ran the universe example on a trial account, you’d have hit a license failure.

New in 4.1: a recipe book for published factors

Until now the skill answered “what is this name?” The new reference file, factor-replication.md, answers a harder question: how do I build this paper’s factor on Portfolio123? It holds 35 recipes across value, quality, earnings quality, momentum, low risk, size and investment, and each one gives the economic definition in a line, the P123 implementation, and the ranking node’s direction and scope.

But the parts I’d read first aren’t the recipes. They’re the 7 constructions Portfolio123 can’t reproduce, each paired with the closest honest proxy instead of a fake, and an 11-row table of substitutions that quietly change the factor you’re building. You won’t find a performance figure anywhere in the file, and that’s deliberate. An alpha we can’t verify from the sources would be an invented fact, and inventing facts is exactly what this skill exists to stop.

The API caught up

Portfolio123 extended its REST API on 28 August 2026 with six new operations, among them GET /dataSeries and GET /rank. api.md now documents all 39 operations of the current spec, and the wrapper map covers all 44 public methods of p123api 3.1.0.

So what breaks when you upgrade the wrapper? Mostly dict access. Nine methods now return typed objects instead of dicts, so res['id'] raises a TypeError, pandas became an optional extra, and Python 3.10 is the floor. We didn’t build the migration table from release notes; we diffed the installed 2.3.0 and 3.1.0 sources.

One correction deserves its own sentence. Version 4.0.0 said Portfolio123 had no Data Series read operation. Since 28 August it does, and the file now says so in those words instead of quietly deleting the old passage.

4.1.1: regional universes, checked live

A community issue and pull request filed in May supplied 19 regional universe IDs that v3.0.0 documented but never verified, because the API spec doesn’t enumerate universes at all. We checked them against the live API. All 19 resolve, and so do TSX, TSXV, CanadaTrust and ALLFUNDCDRCAD. But CDR, reported alongside them, isn’t a universe, and ALLFUND, whose “All Fundamentals” label reads like every market, holds US-listed securities only (foreign companies appear through their US lines and ADRs).

The check also found a trap worth knowing before you merge regions: the same company carries a different p123Uid on each of its listings, so a join on p123Uid across regions silently misses those pairs.

How do you test a universe ID without a regional data license? Ask for it. An unknown ID comes back “not found”, a real one outside your subscription comes back “not in your subscribed regions”, and neither answer costs a credit.

What we still don’t know

Version 4.1.0 was built without spending a single API credit, so three facts in api.md are still stated as open rather than settled, each waiting on one live call. Does POST /rank/create return a bare integer, as the spec says, or an object carrying an id, as the wrapper expects? If it’s the integer, rank_create raises after the ranking system already exists on the server, and the file tells Claude to recover the new id with rank_get(name=...). Is the XML field on GET /rank called nodes or xml? And does the new contains_header_row=True default drop the first row of a headerless CSV? That last one is the only 2.x-to-3.x change that alters results instead of raising an error, and it hasn’t been observed live. I’d rather print the question than guess the answer.

How to install it

In Claude (claude.ai and the desktop app, including Chat and Cowork)

  1. Download portfolio123.skill from the v4.1.1 release on GitHub.
  2. In Claude, open Settings, go to Capabilities, then Skills, and click “Upload skill”.
  3. Select the downloaded portfolio123.skill file.

Skills require a paid plan with code execution enabled.

In Claude Code (CLI and IDE)

  1. Download and unzip portfolio123.skill. It is a standard zip archive.
  2. Move the portfolio123 folder into your skills directory: ~/.claude/skills/portfolio123 to have it in all projects, or .claude/skills/portfolio123 inside a single project. If an older version is already there, replace that folder.
  3. Start a new Claude Code session and ask anything P123 related. The skill loads on its own.

The README on GitHub also covers Cursor.

Get the skill

Most of the mistakes this release fixes used real Portfolio123 names. That’s the habit I’d keep, whatever assistant writes your formulas: check the window and the defaults, not just the spelling.

Download portfolio123.skill v4.1.1 from GitHub

The skill is MIT licensed and open source. The code, the full changelog and the issue tracker are on GitHub, and several fixes in this release started as reports from people using the skill on real work. If you find the next one, that’s where it goes. The first release post explains what the dictionary covers and how we verified it.

Considering a quantitative approach?

Begin with a free 45-minute introductory conversation to assess fit, scope and approach.

Request an introductory consultation
Request a consultation · free, 45 min, no commitment