2026-01-23 06:21:10
Java's checked exceptions were a massive improvement over C's error-handling mechanism. As time passed and experience accumulated, we collectively concluded that we weren't there yet. However, Java's focus on stability has kept checked exceptions in its existing API.
\ Java 8 brought lambdas after the "checked exceptions are great" trend. None of the functional interface methods accepts a checked exception. In this post, I will demonstrate three different approaches to making your legacy exception-throwing code compatible with lambdas.
Consider a simple exception-throwing method. \n
public class Foo {
public String throwing(String input) throws IOException {
return input; //1
}
}
\
The method accepts a String and returns a String. It has the shape of a Function<I, O>, so we can use it as such: \n
var foo = new Foo();
List.of("One", "Two").stream()
.map(string -> foo.throwing(string))
.toList();
The above code fails with a compilation error: \n
unreported exception IOException; must be caught or declared to be thrown
.map(string -> foo.throwing(string)).toList();
^
1 error
To fix the error, we need to wrap the throwing code in a try-catch block: \n
List.of("One", "Two").stream()
.map(string -> {
try {
return foo.throwing(string);
} catch (IOException e) {
return "";
}
}).toList();
At this point, the code compiles, but defeats the main purpose of lambdas: being concise and readable.
We can definitely improve the design by modeling a Function with a throwing apply(). \n
interface ThrowingFunction<I, O, E extends Exception> {
O apply(I i) throws E;
}
We can then provide a wrapper to transform such a throwing Function into a regular Function. \n
class LambdaUtils {
public static <I, O, E extends Exception> Function<I, O> safeApply(ThrowingFunction<I, O, E> f) {
return input -> {
try {
return f.apply(input);
} catch (Exception e) {
return "";
}
};
}
}
With the above, the calling code can be improved like this: \n
var foo = new Foo();
List.of("One", "Two").stream()
.map(string -> LambdaUtils.safeApply(foo::throwing)) //1
.toList();
The most straightforward way to call exception-throwing code in a lambda involves using a library. Two libraries that I know of provide this capability:
Here's how we can rewrite the above code using Commons Lang 3 code: \n
var foo = new Foo();
FailableFunction<String, String, IOException> throwingFunction = foo::throwing; //1
List.of("One", "Two").stream()
.map(throwingFunction)
.recover(e -> "") //2
.toList();
Function
recover() mimics the value set in the previous catch block\ The libraries improve upon my debatable design above, but the idea stays the same.
\ The decision to roll out your own or use a library depends on a variety of factors that go beyond this post. Here are some criteria to help you.
Checked exceptions are a compile-time concern. The Java Language Specification states:
\
A compiler for the Java programming language checks, at compile time, that a program contains handlers for checked exceptions, by analyzing which checked exceptions can result from execution of a method or constructor. For each checked exception which is a possible result, the
throwsclause for the method (§8.4.6) or constructor (§8.8.5) must mention the class of that exception or one of the superclasses of the class of that exception. This compile-time checking for the presence of exception handlers is designed to reduce the number of exceptions which are not properly handled.
\ We could potentially hook into the compiler to prevent this check via a compiler plugin. Or find a library that does. That's when Manifold enters the scene.
\
Manifold is a Java compiler plugin. Use it to supplement your Java projects with highly productive features.
Powerful language enhancements improve developer productivity.
- Extension methods
- True delegation
- Properties
- Optional parameters (New!)
- Tuple expressions
- Operator overloading
- Unit expressions
- A Java template engine
- A preprocessor
- …and more
\ Disclaimer: I don't advocate for using Manifold. It makes the language you work with different from Java. At this point, you'd be better off using Kotlin directly.
\ Using Manifold to suppress checked exceptions is a two-step process. First, we add the Manifold runtime to the project: \n
<dependency>
<groupId>systems.manifold</groupId>
<artifactId>manifold-rt</artifactId>
<version>${manifold.version}</version>
<scope>provided</scope>
</dependency>
\ Then, we configure the compiler plugin: \n
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<source>11</source>
<target>11</target>
<encoding>UTF-8</encoding>
<compilerArgs>
<arg>-Xplugin:Manifold</arg>
</compilerArgs>
<annotationProcessorPaths>
<path>
<groupId>systems.manifold</groupId>
<artifactId>manifold-exceptions</artifactId>
<version>${manifold.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
\ At this point, we can treat checked exceptions as unchecked. \n
var foo = new Foo();
List.of("One", "Two").stream()
.map(string -> foo.throwing(string)) //1
.toList();
In this post, I tackled the issue of integrating checked exceptions with lambdas in Java. I listed several options: the try-catch block, the throwing function, the library, and Manifold. I hope you can find one that suits your context among them.
\ To go further:
Originally published at A Java Geek on January 18th, 2026
2026-01-23 05:35:18
DAVOS
Today marks the launch of AlphaTON Claude Connector, a groundbreaking platform that combines Anthropic's Claude artificial intelligence with TON blockchain technology, delivered through the Telegram messaging application. The solution enables users to manage digital assets, execute transactions, and interact with blockchain services using natural language conversation.
The platform addresses a critical barrier to cryptocurrency adoption: complexity. Traditional blockchain interfaces require technical knowledge and navigation through complicated dashboards. AlphaTON Claude Connector eliminates these obstacles by allowing users to simply type commands in plain English within their existing Telegram application.
The platform integrates three major technologies:
Users can perform operations such as checking wallet balances, sending and receiving TON tokens, viewing transaction histories, and managing digital assets all through conversational commands.
Logan Golema, Chief Technology Officer, AlphaTON Capital, said, “Building with Claude Code has been essential to our internal development process, enabling us to move faster and collaborate more effectively across teams. We’re excited to extend that capability through this connector and empower Telegram and TON developers worldwide with more efficient, scalable tools to build and innovate.”
\n Key Capabilities
Conversational Interface
Users interact with the system through natural language. Rather than navigating complex menus, users simply state their intent:
The AI interprets the request, executes the appropriate blockchain operation, and confirms completion.
For users requiring visual interfaces, the platform includes an embedded web application accessible directly within Telegram. This Mini App provides:
The platform connects with project management systems including JIRA, enabling business teams to coordinate blockchain operations within existing workflows.
Built on the Model Context Protocol standard, the system provides extensible architecture for developers to build custom integrations and applications.
The global cryptocurrency market continues to expand, yet mainstream adoption remains limited by usability challenges. Research indicates that complexity ranks among the top barriers preventing new users from engaging with digital assets.
Messaging-based interfaces represent a significant opportunity to bridge this gap. By meeting users within applications they already use daily, AlphaTON Claude Connector removes friction from the onboarding process.
The TON blockchain, with its native Telegram integration and high transaction throughput, provides an ideal foundation for this approach.
The platform implements enterprise-grade security practices:
AlphaTON Claude Connector is now available.
Claude users can attach the custom connector in their desktop or CLI environments.
For enterprise inquiries, partnership opportunities, or media requests, contact the team through official channels.
The Open Network (TON) is a decentralized blockchain designed for speed and scalability. Originally developed by the team behind Telegram, TON has grown into an independent ecosystem with an active developer community and expanding use cases across payments, decentralized applications, and digital identity.
Claude is an AI assistant developed by Anthropic, designed to be helpful, harmless, and honest. Claude excels at nuanced conversation, complex reasoning, and following detailed instructions, capabilities essential for reliable blockchain operations.
AlphaTON Capital Corp (NASDAQ: ATON) is the world's leading technology public company scaling the Telegram super app, with an addressable market of 1 billion monthly active users while managing a strategic reserve of digital assets.
The Company implements a comprehensive M&A and treasury strategy that combines direct digital assets acquisition, validator operations, and strategic ecosystem investments to generate sustainable returns for shareholders.
Through its operations, AlphaTON Capital provides public market investors with institutional-grade exposure to the TON ecosystem and Telegram's billion-user platform while maintaining the governance standards and reporting transparency of a Nasdaq-listed company.
Led by Chief Executive Officer Brittany Kaiser, Executive Chairman and Chief Investment Officer Enzo Villani, and Chief Business Development Officer Yury Mitin, the Company's activities span network validation and staking operations, development of Telegram-based applications, and strategic investments in TON-based decentralized finance protocols, gaming platforms, and business applications. \n AlphaTON Capital Corp is incorporated in the British Virgin Islands and trades on Nasdaq under the ticker symbol "ATON". AlphaTON Capital, through its legacy business, is also advancing first-in-class therapies targeting known checkpoint resistance pathways to achieve durable treatment responses and improve patients' quality of life.
AlphaTON Capital actively engages in the drug development process and provides strategic counsel to guide the development of novel immunotherapy assets and asset combinations. To learn more, please visit https://alphatoncapital.com/.
This press release contains forward-looking statements within the meaning of the Private Securities Litigation Reform Act of 1995. These statements relate to future events or AlphaTON's future financial performance and involve known and unknown risks, uncertainties and other factors that may cause actual results to differ materially from those expressed or implied by these forward-looking statements. Factors that could cause or contribute to such differences include, but are not limited to, the development and adoption of AI technologies, market volatility, regulatory developments, technical challenges in infrastructure deployment, and general economic conditions. AlphaTON undertakes no obligation to update any forward-looking statements, except as required by law.
Technology Disclaimer
The AlphaTON Claude Connector utilizes emerging artificial intelligence and blockchain technologies that are under active development. Features, functionality, and performance may evolve over time and are subject to change without notice. While it is designed to enhance usability and efficiency, users should independently evaluate the technology and exercise appropriate caution when engaging in digital asset transactions. AlphaTON Claude Connector does not provide financial, investment, or legal advice.
Investor Relations: \n AlphaTON Capital Corp \n [email protected] \n (203) 682-8200 \n \n Media Inquiries: \n Richard Laermer \n RLM PR \n [email protected] \n (212) 741-5106 X 216
:::tip This story was published as a press release by Btcwire under HackerNoon’s Business Blogging Program. Do Your Own Research before making any financial decision
:::
\ \
2026-01-23 05:32:55
In this article, we will create a WEB application using the latest version of Angular and integrate the AWS WAF (Web Application Firewall) CAPTCHA challenge to protect against bots.
Before we begin, you need to install and configure the tools below to create the Angular application and integrate it with the AWS WAF captcha.
\
AWS WAF (Web Application Firewall) is a security service designed to protect your WEB applications and APIs from exploits of common internet vulnerabilities and bots that can affect availability, compromise security, or consume excessive resources.
\ 1. Let's access the AWS account. Access the site https://aws.amazon.com/waf/, and click on the link Sign in to console.
Note:
\ 2. Now, we will fill in the field Account ID or alias, fill in the field IAM username, fill in the field Password, and click on the button Sign in.
3. Next, we will type waf in the search field and click on the option WAF & Shield.
4. Then, we will click on the menu Application integration.
5. After clicking on the menu Application integration, we will click on the tab CAPTCHA integration.
6. Now, we will click on the option CloudFront JavaScript tag, click on the button Copy JavaScript tag to copy the URL of the JavaScript file, because this URL will be configured in the Angular application, and click on the button Generate API key.
7. Next, we will click on the option CloudFront, fill in the field Domain with your website's domain, and click on the button Generate API key.
8. Then, we will click on the icon to copy the API key because this API key will be configured in the Angular application.
9. Ready! The API key was created.
Angular is a development platform for building WEB, mobile, and desktop applications using HTML, CSS, and TypeScript (JavaScript). Currently, Angular is at version 21, and Google is the main maintainer of the project.
\
1. Let's create the application with the Angular base structure using the @angular/clitool with the AI configuration files disabled, the server-side rendering (SSR) disabled, the route file disabled, and the SCSS style format. \n
ng new angular-aws-waf-captcha --ai-config=none --ssr=false --routing=false --style=scss
CREATE angular-aws-waf-captcha/README.md (1473 bytes)
CREATE angular-aws-waf-captcha/.editorconfig (314 bytes)
CREATE angular-aws-waf-captcha/.gitignore (604 bytes)
CREATE angular-aws-waf-captcha/angular.json (2084 bytes)
CREATE angular-aws-waf-captcha/package.json (970 bytes)
CREATE angular-aws-waf-captcha/tsconfig.json (957 bytes)
CREATE angular-aws-waf-captcha/tsconfig.app.json (429 bytes)
CREATE angular-aws-waf-captcha/tsconfig.spec.json (441 bytes)
CREATE angular-aws-waf-captcha/.vscode/extensions.json (130 bytes)
CREATE angular-aws-waf-captcha/.vscode/launch.json (470 bytes)
CREATE angular-aws-waf-captcha/.vscode/tasks.json (978 bytes)
CREATE angular-aws-waf-captcha/src/main.ts (222 bytes)
CREATE angular-aws-waf-captcha/src/index.html (306 bytes)
CREATE angular-aws-waf-captcha/src/styles.scss (80 bytes)
CREATE angular-aws-waf-captcha/src/app/app.scss (0 bytes)
CREATE angular-aws-waf-captcha/src/app/app.spec.ts (690 bytes)
CREATE angular-aws-waf-captcha/src/app/app.ts (246 bytes)
CREATE angular-aws-waf-captcha/src/app/app.html (20086 bytes)
CREATE angular-aws-waf-captcha/src/app/app.config.ts (203 bytes)
CREATE angular-aws-waf-captcha/public/favicon.ico (15086 bytes)
✔ Packages installed successfully.
Successfully initialized git.
\ 2. Now, we will install and configure the Bootstrap CSS framework. We will do steps 2 and 3 of the post Adding the Bootstrap CSS framework to an Angular application.
\
ng generate environments
CREATE src/environments/environment.ts (31 bytes)
CREATE src/environments/environment.development.ts (31 bytes)
UPDATE angular.json (2309 bytes)
\
4. Then, we will configure the variable aws.waf.url with the URL of the JavaScript file containing the AWS WAF integration code and the variable aws.waf.apiKey with the API key that was created in AWS WAF in the src/environments/environment.ts and src/environments/environment.development.tsfiles as below. \n
aws: {
waf: {
url: 'https://a162a8302aaa.edge.captcha-sdk.awswaf.com/a162a8302aaa/jsapi.js',
apiKey: 'QprVjPcLgWgjYBGZoci9OMw9CFJSZZtr2gHt7McsehfL1+Hi+6Rp5y99a0p3vmdsq5Wkat06xfZSTc6dfjvR5w9COBfYhcsXvdRPAGSd9Zxfx6W2QfDsDc2IdiQImVfAl35Uw3tBYd31B3rVlT9q4pEcipVFo29NcqRjYneV7peX2Q+vvd4ttjX0QuM3d+csxtCjaHYSquk6nySEun5QTnbUsq0TE2gliQRFYgHFX9vXSWrkkAXHwWtaxr86kzIeIPoesRAC3JB7kwyK6l4sYoo6w7fTSougEwpjJHGIo8LHdjlxmmNpE2umf1z1go3Ixjm/ujc919tn2FCuGbnW4OEXVWotx3qjf+FPkFbght+ccXsXsL2eHoPgj0sHKaeK0fYpGlJnpwDp+ep64+UVm46Y7Udr7RVLjCnngBcgTRnmA20uy+agfhRnBJk6Y34OgJQJnWuoYXCoVETlFus4ATJ69dny8/6GxUUObjcU6gnfpyR5vkaqmKwSluu6i/x90o9pm1/TTFeh4iuSGylrMySzOe4PsxqMOYR9ow9hnrm7fXz+yE2GoQUJjLWpOUfcmcFmOonjslxIxwDjafWBPACec3JBWGYjAF0H+98Bg6vPly9wlxJwiz6eiMjULPfb1lM7rr6crZ1VaZ964pw21FZSrOdAMknmGSZvmKGAzeU=_1_1',
},
},
\
5. After configuring the variables, we will remove the content of the App class from the src/app/app.ts file, create the loadScript and renderCaptcha methods, and implement the ngAfterViewInit method of the AfterViewInit class that it will execute the loadScriptmethod as below. \n
export class App implements AfterViewInit {
captchaRef = viewChild>('captcha');
messageSuccess = model('');
messageError = model('');
constructor() {
}
ngAfterViewInit(): void {
this.loadScript();
}
private loadScript(): void {
if (document.getElementById('awsWafScript')) {
return;
}
const script = document.createElement('script');
script.id = 'awsWafScript';
script.async = false;
script.defer = true;
script.src = environment.aws.waf.url;
script.onload = () => {
this.renderCaptcha();
};
document.head.appendChild(script);
}
private renderCaptcha(): void {
const captchaElementRef = this.captchaRef();
if (window.AwsWafCaptcha && captchaElementRef) {
window.AwsWafCaptcha.renderCaptcha(captchaElementRef.nativeElement, {
apiKey: environment.aws.waf.apiKey,
onSuccess: (token: string) => {
this.messageSuccess.set(`Captcha successfully validated! Token: ${token}`);
this.messageError.set('');
},
onError: (error: any) => {
this.messageError.set(`Error validating captcha: ${error}`);
this.messageSuccess.set('');
},
});
}
}
}
\
6. Now, we will remove the content from the src/app/app.html file and add the div tag with the captchareference variable as below. \n
<div class="container-fluid py-3">
<h1>Angular AWS WAF Captcha</h1>
<div class="row mt-3">
<div class="col-sm-12">
<div #captcha></div>
</div>
</div>
<div class="row mt-3">
<div class="col-sm-12">
<p class="text-center text-success">{{ messageSuccess() }}</p>
<p class="text-center text-danger">{{ messageError() }}</p>
</div>
</div>
</div>
\
npm run start
> [email protected] start
> ng serve
Initial chunk files | Names | Raw size
styles.css | styles | 377.03 kB |
main.js | main | 6.10 kB |
| Initial total | 383.13 kB
Application bundle generation complete. [2.375 seconds] - 2026-01-17T18:13:56.184Z
Watch mode enabled. Watching for file changes...
NOTE: Raw file sizes do not reflect development server per-request transformations.
➜ Local: http://localhost:4200/
➜ press h + enter to show help
\
8. Then, we will access the URL http://localhost:4200/ and check if the application is working.
9. Ready! The Angular application was created and integrated with the AWS WAF CAPTCHA challenge.
\ The application repository is available at https://github.com/rodrigokamada/angular-aws-waf-captcha.
Summarizing what was covered in this article:
\ You can use this article to create web applications with bot protection using the AWS WAF captcha challenge.
\ Thank you for reading, and I hope you enjoyed the article!
\ This tutorial was posted on my blog in Portuguese.
\ To stay updated whenever I post new articles, follow me on Twitter and LinkedIn.
2026-01-23 05:14:47
We’d like to think that crypto is completely independent from traditional money, but that’s not the case yet. Case in point, every time the Federal Reserve (Fed) decides to alter their interest rates, most financial markets react —and that includes cryptocurrencies. Central banks still have enough power to heavily influence global money conditions, and how investors behave based on that.
\ You see, we all use loans, and loans often come with interest rates attached. That’s why when borrowing is cheap (because of low rates), money flows with confidence. Now, when borrowing gets expensive, investors turn cautious. Crypto is just another asset in this financial ocean, and it moves with the tide. Let’s see more of how this works.
The Federal Reserve is the central bank of the United States, which means it’s the one and only institution in charge to mint and manage the supply of US Dollars (USD). It also supervises the financial firms that use this asset, and tries to keep their economy steady. One of its main tools is the Federal funds rate, which dictates how expensive it’s for banks to borrow reserves from each other overnight.
\

When that rate goes up, borrowing feels (for everyone using dollars) like climbing a hill with extra weight. When it goes down, the load eases, and credit moves with more comfort. We may like it or not, but the USD is still the most used currency worldwide. Therefore, changes on its interest rates are never limited to the United States. They have international consequences, shaping costs for companies, investors, and governments alike. Once the Fed sends a signal, money shifts position like a flock of birds changing direction mid-flight.
\ Of course, crypto traders are also affected. In periods of low rates, investors feel bolder and lean toward riskier assets (like cryptos, yes). On the contrary, when rates go up, people seek safer assets. Prices quickly reflect this scenario: a chain reaction that starts with central banks and travels through global markets until it reaches every portfolio, including those filled with tokens.
Risk assets like cryptocurrencies tend to react fast to any shift in global liquidity. That’s why we see prices going up and down almost immediately after every announcement. For instance, when the Fed pushed rates higher throughout 2022, there was a chill in the markets. A study by Yale University found a clear correlation between US monetary policies and digital asset volatility, indeed.
\

We saw a concrete example in December 2022, when the Fed raised its interest rates. Bitcoin and Ethereum values plummeted in a matter of hours after the announcement, while the uncertainty of tighter conditions in global markets spread throughout the investment community.
\ The opposite case came in July 2024: The Fed hinted that it might hold off on further increases, and global traders welcomed the shift instantly. Crypto prices brightened as confidence returned.
\ But wait there, this isn’t just about the US Fed. Crossing the ocean, when the European Central Bank (ECB) adjusts its policies, crypto might feel it, too.
\ This region is also an important financial center globally, so, when credit conditions here change, investors react. Low rates mean more investments and potential bullish markets. High rates mean the opposite. In the end, crypto is also part of the global economy, and it can move in tandem with it.
Remember: central bank rates are temporary, but crypto was built to outlast them. To outlast the fragile fiat system, indeed. These distributed networks were born with the goal to create a method for the transfer of value from one individual to another without the need for a central authority, with neither permission nor censorship by external parties or traditional monetary policies.
\ Bitcoin has provided a medium of exchange that’s decentralized, transparent, censorship-resistant, and open to everyone. Networks like Obyte have taken this one step further by eliminating all intermediaries (miners and “validators”), so no one can be an obstacle for their payments and transactions.

With the increasing acceptance of digital currencies worldwide, we can say there will be less reliance on interest rate announcements over time. Knowing how today’s central banking operations can affect crypto markets can be useful to avoid panic. However, the long game belongs to the technology, not bank announcements. Prices will always swing, for one reason or another. The noise will fade, and the stronger system will prevail.
Featured Vector Image by pinnacleanimates / Freepik
2026-01-23 00:02:54
How are you, hacker?
🪐 What’s happening in tech today, January 22, 2026?
The HackerNoon Newsletter brings the HackerNoon homepage straight to your inbox. On this day, Apple aired its iconic "1984" commercial during the Super Bowl in 1984, In historic Roe v. Wade decision, the right to abortion was made a federal right in 1973, Kmart Corporation filed for Chapter 11 bankruptcy in 2002, and we present you with these top quality stories. From 5 Risks You Have To Take as a Leader to What Happens When Novelists Write Like Developers, let’s dive right in.

By @burvestorylab [ 7 Min read ] Swap Word for an IDE: use VS Code, Markdown, Git version control/branches, and built-in AI to draft, revise, and safeguard your novel like a developer. Read More.

By @giovannicoletta [ 12 Min read ] A school killing in Italy exposes deeper failures in education and politics. Data, AI, and debate-based learning may offer a long-term solution. Read More.

By @vinitabansal [ 12 Min read ] Here are the 5 risks every leader must take daily because it’s impossible to get better at anything without consistent practice. Read More.
🧑💻 What happened in your world this week?
It's been said that writing can help consolidate technical knowledge, establish credibility, and contribute to emerging community standards. Feeling stuck? We got you covered ⬇️⬇️⬇️
ANSWER THESE GREATEST INTERVIEW QUESTIONS OF ALL TIME
We hope you enjoy this worth of free reading material. Feel free to forward this email to a nerdy friend who'll love you for it.See you on Planet Internet! With love, The HackerNoon Team ✌️

2026-01-22 23:34:22
We had a problem. Our automated trading system had a positive expected value: the math checked out, the backtests looked great, and initially, it made money. But over time, it was bleeding. Small losses that accumulated faster than the occasional wins could compensate.
This wasn't a bug in the code. It was a fundamental misunderstanding of what matters in production.
Most trading tutorials, academic papers, and online courses teach you to maximize expected value. The logic seems bulletproof:
E[profit] = Σ(probability_i × outcome_i)
If this number is positive, you should take the trade. If you can make this number bigger, you should optimize for it. Simple, right?
Except in production, this optimization strategy has a fatal flaw: it doesn't account for the path you take to reach that expected value.
Let me show you what I mean with a real scenario from our system.
Our strategy was designed to capture price spikes in volatile markets. The model would:
On paper, the expected value was solidly positive. In practice:
The problem? Our optimizer had developed a structural bias. It was systematically taking positions that won big occasionally but lost small amounts frequently. The expected value calculation said this was fine: the big wins would eventually compensate. But "eventually" requires infinite capital and infinite time horizon.
We had neither.
To illustrate why these risk controls matter, let's compare two strategies trading the same market over one year:
Strategy A (EV Maximization): Aggressive position sizing based purely on expected value, using 150% leverage when opportunities look good.
Strategy B (Risk-Controlled): Same market signals, but with fractional Kelly sizing (40% of aggressive) and CVaR-based position reduction during high tail risk periods.

The results tell a crucial story. Look at the left chart closely - most EV-maximization paths aren't catastrophically failing. They're just… not compounding. You can see the sawtooth pattern: occasional spikes up, followed by slow erosion. This is the insidious bleeding that positive expected value misses.
Notice how a few paths reached $500k? Those outliers pull the mean up to $146k. But the median is only $136k, and 29 out of 100 paths end below starting capital. In a backtest, you might have gotten lucky and seen one of those winner paths. In production, you get one random draw.
The right chart is "boring", and that's exactly the point. No moonshots to $500k, but also no catastrophic drawdowns. The risk-controlled strategy clusters tightly around modest growth. It survives to compound returns over multiple years.
This is the production reality: the strategy that survives gets to compound. The strategy that bleeds out makes nothing, regardless of what the expected value calculation promised.
This is the classic gambler's problem, formalized by the Kelly Criterion. Even with positive expected value, if your position sizing is wrong, you will go broke.
Consider: You have $100,000 capital and a trade with 60% win probability that either doubles your bet or loses it. Expected value is positive (+20%). But if you bet everything, you have a 40% chance of losing it all on the first trade.
Kelly tells you the optimal bet size is:
kelly_fraction = (p * b - q) / b
# where p = win probability, q = loss probability, b = odds
But here's what we learned in production: even Kelly is too aggressive.
Why? Because:
We ended up using fractional Kelly (25-50% of the theoretical Kelly bet) because the real-world costs of overestimating your edge are catastrophic.
One morning, our system crashed during an extreme weather event. Not a software crash, but a mathematical one.
Our covariance matrix became singular. The optimizer couldn't find a solution. We were frozen, unable to trade, during the exact conditions where our strategy should have made the most money.
The problem: we had optimized for expected scenarios. But extreme events have different correlation structures. Assets that normally move independently suddenly become perfectly correlated. Your carefully estimated covariance matrix, built from thousands of normal days, becomes useless.
The fix wasn't better expected value calculations. It was regularization:
from sklearn.covariance import LedoitWolf
# Instead of sample covariance
cov_matrix = np.cov(returns.T)
# Use shrinkage towards structured estimator
lw = LedoitWolf()
cov_matrix_robust = lw.fit(returns).covariance_
This trades off some accuracy in normal times for stability in extremes. Your expected value calculations will be slightly worse. Your system will survive black swans.
Here's a problem that doesn't show up in backtests: your expected value calculation assumes you can wait long enough for the law of large numbers to work.
In production, you can't.
We discovered this when our system showed strong positive expected value over 90-day windows but consistently lost money over 30-day windows. The problem wasn't the math. It was the business reality.
Our capital providers reviewed performance monthly. Our risk limits were adjusted quarterly based on recent results. If we had three bad months, our position limits got cut, regardless of what the long-term expected value said.
The theoretical strategy needed 6-12 months to reliably show profit. The operational reality gave us 3 months before consequences kicked in.
We had to add explicit time-horizon constraints to our optimization:
def optimize_with_horizon_constraint(scenarios, max_horizon_days=30):
"""
Optimize not just for long-term EV, but for probability of
positive returns within operational time horizon
"""
# Standard expected value
ev = np.mean(scenarios)
# But also: what'sthe probability we're profitable
# within our actual time horizon?
rolling_returns = pd.Series(scenarios).rolling(max_horizon_days).sum()
prob_profitable_in_horizon = (rolling_returns > 0).mean()
# Penalize strategies with low short-term win probability
# even if long-term EV is great
if prob_profitable_in_horizon < 0.6:
return ev * 0.5 # Heavily discount
return ev
This meant accepting strategies with slightly lower theoretical expected value but higher probability of showing profit within our operational constraints. It's not mathematically optimal, but it's practically necessary.
After painful lessons, here's what we learned to optimize for:
Instead of maximizing E[profit], we minimize CVaR (Conditional Value at Risk): the expected loss in the worst 5% of scenarios
import cvxpy as cp
# Decision variable: position sizes
positions = cp.Variable(n_assets)
# Scenarios returns
scenario_returns = get_price_scenarios() # shape: (n_scenarios, n_assets)
portfolio_returns = scenario_returns @ positions
# CVaR constraints
alpha = 0.05 # 5% tail
var = cp.Variable()
u = cp.Variable(n_scenarios)
constraints = [
u >= 0,
u >= -(portfolio_returns - var),
]
cvar = var + cp.sum(u) / (n_scenarios * alpha)
# Optimize for return while constraining tail risk
objective = cp.Maximize(cp.sum(portfolio_returns) / n_scenarios - lambda_risk * cvar)
This explicitly penalizes strategies that have good average returns but catastrophic tail risk.
We assume our model is wrong and optimize for the worst-case within a reasonable uncertainty bound:
# Instead of single expected return estimate
mu_estimated = historical_returns.mean()
# Assume uncertainty
mu_lower_bound = mu_estimated - 2 * historical_returns.std() / np.sqrt(len(historical_returns))
# Optimize for worst-case in uncertainty range
# (Robust optimization / minmax approach)
This protects against overconfident parameter estimates.
We explicitly limit position sizes based on Kelly criterion, even when the optimizer wants more:
def kelly_position_limit(edge, volatility, capital, max_kelly_fraction=0.25):
"""
edge: expected return per unit risk
volatility: standard deviation of returns
max_kelly_fraction: fraction of theoretical Kelly to actually use
"""
kelly_full = edge / (volatility ** 2)
kelly_fraction = capital * kelly_full * max_kelly_fraction
return kelly_position
We use 25% Kelly as a hard constraint. Yes, this reduces expected value. It also ensures we'll still be trading next month.
The shift from expected value thinking to production thinking is philosophical:
Research mindset: "What strategy has the highest expected return?"
Production mindset: "What strategy will survive being wrong about my assumptions?"
Here are the practical shifts we made:
Expected value is a beautiful mathematical concept. It's clean, intuitive, and theoretically optimal.
It's also not enough.
In production, you're not trading against a probability distribution. You're trading against:
The systems that survive aren't the ones with the highest expected value. They're the ones that remain robust when the model is wrong, markets shift, and black swans appear.
Optimize for survival first. Profitability second. Expected value is a component of that calculation, but it's not the objective function.