Full Width [alt+shift+f] Shortcuts [alt+shift+k]
Sign Up [alt+shift+s] Log In [alt+shift+l]
40

Is technical analysis just stock market astrology?

from Alice GG [alt+shift+b] in programming

Technical analysis is a part of finance that studies price moves to guide investment decisions. A lot of investors seem skeptical of the use of past price data, which leads to technical analysis often being perceived as similar to astrology. In this article, I will try to see if it can provide an edge to long-term investors and if it beats reading the horoscope. Chris Liverani Moving Average Crossover There are hundreds of different technical analysis strategies and indicators out there. For this article, I decided to pick what seemed to be one of the simplest: SMA crossovers. Simple Moving Averages (SMA) are, as the name suggests, just an average of past closing prices. The SMA Crossover strategy uses two moving averages, a “fast” one (50 days) and a “slow” one (200 days), and compares them to decide on buying or selling an asset. If the fast SMA is above the slow one, we should buy and hold the stock, and if this condition inverts, we should sell. It is a heuristic around momentum, which is the idea that if an asset price starts rising, we can jump on the bandwagon and hope it will continue its trajectory. I have backtested an SMA crossover strategy on the SPY ETF, one of the most traded passive investment funds in the world. My backtest makes the following assumptions: we do not pay any transaction fees we will obtain exactly the close price when buying or selling dividends received while holding stocks are immediately reinvested cash yields no interests While someone who would have bought 10.000$ of SPY in July 1998 and continuously held the stock would have ended up with 52.030$ in June 2023 (6.78% annualized), an investor using the SMA crossover strategy would have made ended up with 49.127$. (6.54%). Even without accounting for transaction costs, the SMA crossover strategy doesn’t provide a significant over-performance to simply buying and holding over a long period. Does this mean that this strategy is completely useless? Actually no, a closer look at...
25th Jul 2023

Stay updated

Get a weekly newsletter with the top 5 articles worth reading every week.

More from Alice GG

Attention is all you have

The Tetris effect is one of psychology’s most easy to reproduce experiments. Simply spend a bit of time playing the eponymous game every day for a few weeks. After a little while, you’ll start recognizing familiar Tetromino shapes in clouds, buildings, and everyday objects. You might even see them appear before your eyes when you start falling asleep. Tom Tang Attention hijacking There’s one lesson the Tetris effect teaches us: whatever you focus on long enough will end up shaping your thoughts. This can be a good thing since it’s how we learn new skills and discover new ideas. Sadly, less and less of our attention is focused intentionally. Instead of picking what we want to see we let other people decide what is supposed to be good for us. Do you want to watch a video? YouTube knows you like cooking and art streams. But why not also recommend a few clips about the stock market bubble, global warming, and the war in Iran. Doomscrolling will make you stay longer and click on a few more ads. Do you want to listen to music? Just open a Spotify playlist and let the algorithm figure out what you like. Please ignore the AI slop they will insert in between real songs to avoid paying royalties to real artists. Do you want to know how your colleagues are doing? Too bad, LinkedIn will bury any relevant career news between the opinion of complete strangers. It is surely just a coincidence that those strangers happen to be shilling whatever Microsoft is invested in at the moment. Do you want the opinion of strangers on a product? Well those Redditors you wanted to ask are probably just a bunch of LLMs talking to a bunch of Russian trolls now. I hope you didn’t value their opinion too much. If, like me and most people, you spend the major part of your day focused on your device, there’s no doubt it’s affecting you. And when you let someone else dictate what appears on your screen, it’s the same as giving them the key to your brain. New York Said Back to an intentional internet The internet wasn’t always like that. Before recommendation algorithms where a thing, you had to decide what you would be doing on the computer. You didn’t really have one big app that you could open and order it to entertain you. Instead, you had a few dozen of bookmarks to websites, each with a specific idea in mind. A site for video game news, that one website with lots of tutorials, a blog about anime that didn’t update often enough, a wiki about a TV show from the 90s… Of course awful things existed on the web. We had Encyclopedia Dramatica and Rotten.com, but you actually had to put the effort to go there if you wanted. Nobody was going to put pictures of dead kids and far-right propaganda as a suggestion after a pancake recipe or a cat video. The good thing is that this intentional internet is still around. It has just been a bit buried below the corporate web, but it’s not very hard to find. After all you’re on this blog, so you probably already have a good idea about it. The main difference between this time and now is you. When you want to get back to reading blogs, RSS feeds, and finish that tutorial instead of doomscrolling shorts, you have to get used to a slower internet. One where content is not infinite and doesn’t get updated every click. But like every habit, the only thing you have to do is to keep at it. And if you pay enough attention to it, something will click in your brain.

21st Sep 2026 • 3 votes
GodotCon Amsterdam 2026

In April, the Godot foundation organized a conference close to their home base: GodotCon Amsterdam. It was a good occasion for us to showcase Paradox Tower and get some beta feedback from other developers. Most importantly it was two entire days of talks about game development in Godot. Here are some of the ones I recommend checking out if you are into it. 1000 rigged AnimationPlayers in 3D, impossible? Having a lot of animated 3D objects in Godot can seriously damage performance. This is something to look for if you’re developing for systems with limited resources, which may rely on the Compatibility renderer (like Android or Switch). Bertrand Bordage explains how to get around this limitation using Vertex Animation Textures. It basically consists of baking an animation into a shader. I had previously never heard of it and this talk really seems like a doable solution for Switch ports of 3D games. The Clone Wars: Defending Godot Games From Reupload Scams Godot games are very easy to reverse engineer. Many developers assume this is not an issue and will only be used by modders and curious players. Sadly, there’s a cottage industry of shady publishers who will take advantage of this to copy your game. I’ve previously talked a bit about technical countermeasures you can use to make this process harder. In this talk, Yasen Dinkov also explores the legal and marketing aspects of the problem. He provides ideas that can make taking down illegal store pages much easier. From model to gameplay in seconds: setting up your Blender Godot pipeline Doing a lot of manual steps can kill your productivity. A big source of this is manually importing 3D assets and setting them up as Godot scenes. Godot comes with a set of tools to speed that up: post-import scripts. Here, Marion Allard explains how to make the best use of it, with step-by-step examples using Blender objects: Make your own fractal! A more relaxed talk to finish, with a short and fun introduction to fractals by Marta Imke. It explores visual math and the different ways you can build fractal images out of simple functions. This is definitely something that can be useful if you want to create some trippy visual effects.

2nd Jul 2026 • 1 votes
Steam nerfed popular upcoming. So what?

In the latest Steam client update, Valve unveiled major changes to its store’s home page. One of the main difference is that the “Popular Upcoming” section, which shows upcoming games now shows a lot fewer games. This seems to worry indie developers who relied on this section as a major driver of visibility around launch. I personally think this is will not change much to how indie games are marketed and might even be a positive for many niche developers. Popular upcoming is dead Now that game development is more accessible than ever, and anyone can post their games on Steam and Epic. Since all those new developers need to market their games, this has created a cottage industry of game marketing influencers. The strategy they teach is basically always a variant of: Make a game (and a demo) Get a lot of people to play the demo during Steam Next Fest Get 6000+ Wishlist Appear in Popular Upcoming ??? Profit Since everyone is running around with approximately the same strategy, it became a very crowded trade. With everyone publishing a more and more polished demo, Next Fest began to have diminishing returns for most developers. In the same way Popular Upcoming was very impactful when maybe 1 or 2 games appeared in it every day, but if it shows a dozen game, it’s not a guarantee of success anymore. And let’s be honest, players have probably been paying less and less attention to this section of the store for a while. Basically every shovelware publisher knows how to game the algorithm and get their new version of Slop Simulator 2027 in their. Long live the Personal Calendar In the same update, Valve introduced a new feature: the Personal Calendar. It’s a whole page which aims at making players discover games that are personalized to their taste. The recommendation algorithm seems to work somewhat decently. I do not think it is entirely based on tags, since it seems to recommend me a lot of “Open World Survival Craft” games, which is not something I usually play. It may be using wishlist behavior of similar players to make recommendations. One of the major differences is that it shows a calendar for the next eight weeks, so games can have a much longer visibility window. If a player of your target audience didn’t browse Steam on the day before your launch, it would miss you on popular upcoming, while now they can It also shows recently released games, in the past 7 days and past month. Contrary to the homepage “Popular New Releases” tab (ex “New & Trending”), which requires a lot of active players, this section seems accessible even to unknown games. Steam is currently recommending me Imago Season with at the moment 0 review and only 2 concurrent players. A new era for niche games? Before this change, it was extremely difficult for developers to market niche games. I know it from first-hand experience, since I have no doubt Dice ‘n Goblins would have been easier to market if it was not the weirdest combination of ideas possible. Because of this, a lot of new indie game developers were advised to stick to a very popular genre. You love real-time strategy? Too bad, you’ll have to make an action roguelike instead. This has led to a loss of creativity in the indie game world. With many developers working on genres that do not interest them, using recycled ideas and aesthetics. I do believe that this new version of Steam might swing the pendulum in the other way. Now that players of niche games can get recommendation customized to their taste, making games for a non-mainstream audience can become viable again.

12th Jun 2026 • 2 votes
Preview Ebitengine shaders with Luluka

Lately, I’ve been experimenting with building games in Ebitengine. It’s a 2D engine that lets you create games using the Go programming language. To be able to iterate faster on visual effects, I have created a tool that lets me preview shaders: Luluka. Kage Shaders For those who feel like they missed an episode, shaders are small programs running on the GPU which can be used to modify the pixels of an image. In games, they are used everywhere to control how a game looks. They can be used create special effects like blurring an image or making your screen look like a CRT from the 90s. Ebitengine has its own shader language called Kage. It is very convenient because it has a syntax extremely close to Go. Close enough that you can even run go fmt to format your Kage files. Under the hood, Ebitengine will automatically convert Kage shaders into a format understandable by the GPU. Quasilyte’s article about Ebitengine shaders is generally the most comprehensive introduction to the subject. You can also learn more about them in the Kage’s desk. Luluka One of the main difference between Ebitengine and other game engines like Godot, is that it doesn’t have a visual editor. This is generally fine, since I’ve spent most of my career avoiding What-You-See-Is-What-You-Get tools in favor of staying inside NeoVim. But for shaders, you can end up spending a lot of time tweaking a few variables until you get them to look right. That’s why I decided to build my own tool that would let me work on a shader in isolation, and quickly change the variables we give it. You can install Luluka using the following command: go install github.com/Tsukumogami-Software/[email protected] Run a shader by pointing it straight to the file, passing textures with -i and uniform values with -u: luluka sample/transition.kage -i image2.png -i image.png -u Steepness:80 -u Seed.0:15 -u Seed.1:100 -u Seed.2:5000 -u Seed.3:5000 -u Speed:0.08 For more convenience, you can use a YAML file to pass your uniform values. This is especially practical when working with arrays or matrices, since commands can get very long: Steepness: 80 Seed: [15.0, 100.0, 5000.0] Speed: 0.08 luluka sample/transition.kage -i image2.png -i image.png -v values.yaml

15th May 2026 • 1 votes
Protecting Godot games against reverse engineering

Godot games are known to be easy to reverse engineer. Simple tools can extract assets and source code from the packaged files. If you are making commercial games you probably want to take some steps to avoid this. Jorien Loman Godot RE Tools The most popular Godot reverse engineering software is gdsdecomp aka Godot RE Tools. It’s very multi-platform, simple to use, and even comes with a GUI. In a few clicks, you can “Recover” a project from an executable or .pck file. Gdsdecomp is able to find back the file structure of the project, every asset you exported, and the source code with full variable and function names. This is actually really well-made software. It even comes with convenient utilities for people who want to patch translations (one of the many use cases of reverse engineering games). Encrypting .pck files First let’s preface this section with a warning. There’s no way to 100% guarantee that it’s going to be impossible to decompile a game, aside from never distributing the executable. The only thing we can do is make reverse engineering more difficult and time-consuming. Anyway, the recommended way of protecting Godot games against reverse engineering is to encrypt the files inside it. This is done using AES-256, and requires compiling custom export templates. You can find the details in the official docs, but the general idea is this: Clone the Godot source code: git clone [email protected]:godotengine/godot.git Generate an AES-256 key (32 bits in hex format): openssl rand -hex 32 > godot.gdkey Put this key in your environment variables: export SCRIPT_AES256_ENCRYPTION_KEY=$(cat godot.gdkey) Compile the new export templates (for wasm in this example): scons platform=web target=template_release && scons platform=web target=template_debug Set the new templates as custom templates in your export: In your export encryption settings, check “Encrypt Exported PCK”, “Encrypt Index”, and do not forget to put the files and folders you want to encrypt in “Filters to include”: Generate an IV (you should use a new one every export): openssl rand -hex 16 Last but not least, set your AES key and IV in the encryption settings page. If you did everything correctly, your exported .pck should not be readable by gdsdecomp without knowing the key. At the same time, players should still be able to play the game as usual without issues or needing to know what AES-256 means. Sadly, the key is stored in plain text in memory, and it is not very hard to find it there. According to an estimate I just made up, it would take a 12 years-old with an hex editor and a YouTube tutorial around 15 minutes to get the key. There’s even a tool that promises it can find it in only 50 ms. Godot-Secure To solve this problem, we need to obfuscate the decryption process a little bit. For those that feel this sounds terribly complicated, there’s a script called Godot-Secure that was built to help you with that. It will modify Godot source code to significantly alter the decryption process. Instead of directly using the key we store in memory, it will use it and a secret token to derivate a second key and decipher the files with it. In addition, to that, it will change a few magic numbers and can switch the algorithm from AES-256 to Camellia-256. Once you have run the script, you will need to recompile both the export templates and the editor. This is because the editor is responsible for encrypting the files during export. After exporting a file with the secured Godot, the attackers can still easily obtain our key from the binary files. However, this key is useless by itself. They will also need to find the secret token, work through the key derivation method and re-implement the decryption algorithm. This can take a lot of time and requires actual programming knowledge. Improving the obfuscation Of course, if you want to play around with some C++, you can make this a bit more robust by adding custom logic of your own. There are two files that will be relevant to you. First one is core/io/file_access_encrypted.cpp. It contains the encryption logic in the function FileAccessEncrypted::open_and_parse and the decryption logic in the function FileAccessEncrypted::_close. CryptoCore::AESContext ctx; ctx.set_encode_key(key.ptrw(), 256); // Due to the nature of CFB, same key schedule is used for both encryption and decryption! ctx.decrypt_cfb(ds, iv.ptrw(), data.ptrw(), data.ptrw()); The second is core/io/file_access_pack.cpp. This one contains how the key is loaded from memory in the PackedSourcePCK::try_open_pack function and FileAccessPack constructor. Be careful when modifying this part, as changes with how you load the key will need to be reflected in how you set the key from the editor. Vector<uint8_t> key; #ifdef TOOLS_ENABLED if (!p_decryption_key.is_empty()) { ERR_FAIL_COND_MSG(p_decryption_key.size() != 32, "Decryption key must be 256-bit."); constexpr uint8_t empty_key[32] = {}; if (memcmp(script_encryption_key, empty_key, sizeof(empty_key)) == 0) { key = p_decryption_key; } } else #endif { key.resize(32); memcpy(key.ptrw(), script_encryption_key, 32); } The script_encryption_key variable itself is set at compile time by the script core/core_builders.py.

3rd Apr 2026 • 1 votes

More in programming

If people would just

Building systems that incentivise good behaviour

19 hours ago • 1 votes
BazelCon 2026 recap

My now-traditional “summary” of the conference along with my own commentary and thoughts.

2 days ago • 1 votes
The Future of CSS ✨

Every year, browser vendors collaborate via the Interop project to synchronize their efforts on new HTML/CSS/JS features. This year, there’s a ton of super exciting features being considered! In this blog post, we’ll explore the CSS of the future, to get a glimpse of what we’ll soon be able to do.

3 days ago • 1 votes
Speeding up code review with `small-change`

Imprint’s average engineer is merging 4x more PRs than 2 years ago. Yay. Aggregated behind the average is something even more interesting: we have two teams that are merging 10x their PRs over that period. One engineer is merging 25x the PRs per week of our average engineer two years ago, and a number are merging 10x. That’s pretty neat, and the slope of the line suggests our average in a year is going to look much closer to today’s p90 than today’s p50. Even more importantly, we aren’t just shipping more, our quality has improved: incidents are down 42% half-over-half, and critical incidents are down 78% half-over-half. I think we’ve always known the quality/velocity tradeoff wasn’t a particularly useful construct, but that’s undeniable today. As we’ve walked this path, we–like everyone else progressing down it–have run into the problem of pull request review. The p50 pull request review took about 33 minutes to complete 2 years ago, but now takes us about 77 minutes. The slope here correlates tightly with the number of pull requests getting merged. Tightly enough that addressing it became one of my priorities for the week. We solved it! Just kidding, we’ve absolutely not solved it, but I think our current approach is an interesting one, which we call the small-change. The work discussed here was shaped and done by many folks at Imprint including Dan, Joy, Daniel, Lenny, Taylor, Ted, and Annie, among many others. Why review pull requests? There are four reasons we review pull requests: Knowledge sharing between author and reviewer – software engineering is generally learned via apprenticeship, and reviews are a primary mechanism of experienced engineers teaching others what good software looks like. We believe the current volume means that this knowledge sharing will have to move towards operating on clusters of pull requests, rather than individual pull requests Preventing errors – review has always been an expensive time to catch errors, and we believe that effective CICD along with harness verification techniques like poteto’s pstack are more effective mechanisms for preventing errors than review Preventing malicious behavior – my experience is that even careful code review will generally miss competent malicious behavior, although fortunately most malicious behavior is incompetent. We believe both sorts of behavior are best identified using a combination of fixed rules (modifying these specific objects/classes/files requires review), anti-abuse mechanisms that we’ve refined in our LLM-based member support experiences, auditing, and audit log inspection Compliance obligations in our documented controls – these can be changed, but today they require that an independent human reviews changes in a subset of our repositories In the modern development paradigm, we think there is a better solution for each of these problems. But, we also want to make these changes very cautiously. Small steps with small-change We believe we move fast by finding narrow, contained ways to validate new practices, so to iterate our way into an effective solution, we’ve developed the concept of a small-change. Here’s how it works: When a pull request is marked ready, CICD determines whether it is eligible to be a small-change. This is represented as a passing Github check. There is also a label for visibility, but it is the check itself, managed by the build and not human modifiable, that determines eligibility. (The label is used for initial filtering, but the check is still independently verified.) Something is a small-change if it meets all of these criteria: It is less than 1,000 lines of code There are no p1 or p2 findings from our ai-code-review automated review bot The author has “experience” in the service or application, defined as 10+ prior merged pull requests into that service or application’s directories. For changes working across multiple services or applications, the author must have experience in all of them to qualify Impacts fewer than N distinct services or applications. N is 1 on our frontend monorepo, and N is 3 in our backend monorepo, where typical changes will modify both a gRPC service and a common HTTP gateway Shared libraries and utilities files are not eligible for small-change Each repository has a .small_change file which allows per-path customization while we continue to tune the behaviors. For example, a service dealing with money movement can be excluded Our Slack automation tags every reference to a pull request with reacji labeling the state of that pull request, for example if it has failing tests, if it has been approved but tests are still running, or if it is ready to merge. We added a small-change reacji that indicates which of those pull requests meet the small-change criteria In our internal skills repository, we created two skills that have been distributed across harnesses: review-small-change which takes a list of repositories and reviews all open, non-draft, small-changes, including providing approval if they meet the review’s criteria (all checks pass including small-change check, and not touching on sensitive topics such as payments and security) review-pr-cluster which reviews batches of pull requests to identify common themes that came up, and suggest opportunities for discussion and adding verifications We set the social expectation that any error caused by a small-change is a failure in our system, and has to be solved at the system level: improvements to ai-code-review, to our verification mechanisms, to our CICD, to our harness, etc. This took about two days of infrequent attention to implement and rollout, although I imagine we will be tuning the knobs here for a long time. Maybe forever. fleet: centrally orchestrated harness I’ll briefly mention our other approach to reducing code review volume, which anchors on our centrally-orchestrated harness, fleet. (Which is similar to Stripe’s Minions although not following the one-shot approach in particular). We rely on fleet to implement and verify software in a highly controlled harness running in the cloud, with independent evaluation mechanisms to identify the correct number of independent reviewers for any given change. That number can be as low as one (e.g. fleet writes, one human reviews) for changes evaluated as safe. Results / next steps / reception I’ll be honest, it’s too early to give a useful result here. From early results, about 10% of changes qualify as a small-change. Those are now eligible for very fast approval, and generally get it unless they trip a flag, generally due to touching a security or money adjacent topic. While 10% is a small percentage, the core concept here is working, and ultimately will succeed or fail based on our ability to expand that percentage over the next few months in tandem with expanding our verification mechanisms to be increasingly comprehensive. This is ultimately going to fail or succeed depending on our ability to improve our verifications, which does require more difficult sorts of techniques to accomplish in low scale-complexity, high domain-complexity software than in the high scale-complexity, low domain-complexity products where many techniques like incremental rollouts are exceptionally effective. (Don’t get me wrong, they still work, they just provide less coverage when most users have different configuration and behavior.) Folks have not been uniformly excited about this, it’s a substantial change from how we’ve learned to be good engineers, and it’s uncomfortable to reevaluate whether a long-held best practice has become merely dogma. The most energizing part of the current cycle is that we get to reevaluate these practices we grew up on every week; the most painful part of the current cycle is that we’re likely to fall behind if we ever stop reevaluating them.

6 days ago • 1 votes
Building a Chestnut Launcher

The park near my house has lots of chestnuts and my kids have been collecting them like crazy (it’s actually their favorite post-school activity). We accumulated quite a hoard. I thought it would be fun to make a launcher so we had something to do with our new chestnut collection. I wanted to go with a very simple crossbow-style design (like the famous D2 item) using latex tubing and a leather pouch for holding the chestnuts. This is what I came up with. It launches chestnuts about 220 feet, and it’s simple enough to build in an afternoon. The frame is a 42 inch 2x2 and a spare IKEA bed slat for the crossbeam, glued and screwed together. A 3/8 inch eye bolt goes through each end of the crossbeam, and the latex tubing is tied to those and to the pouch from a leather shepherd’s sling. Tying the tubing was the fiddliest part. It has to be stretched while you wrap it with butcher’s twine, so I clamped a couple of scrap blocks to my workbench to hold it. I like this design because the tubing can be wrapped around the eye bolts to easily add more tension and power. The Trigger My favorite part of the design was that I decided to use an archery release like this one for the trigger. It provides a safe and reliable way to hold the tubing back, and it’s made to let go cleanly. I 3D printed a little housing that mounts the release securely to the back of the stock, and the release clips onto a loop of archery D-loop cord on the back of the pouch. Then I added a dowel for a rear grip and an old handle I had previously removed from my shop vac. How Well Does It Work? We tried it at the park and it works surprisingly well. Aimed at about 35 to 40 degrees, it sends our chestnuts (on the small side, about 10 to 15 grams) about 220 feet. Thanks to the archery release, we haven’t had a single misfire. I got curious and did some rough math. To go that far with air drag, the chestnuts are leaving at somewhere around 85 to 100 mph, which works out to about the same energy as a paintball. So safety glasses are important and you never point it at anyone. You can find the 3D print on Printables and a full build guide on Instructables. Make sure to always use it with adult supervision :)

6 days ago • 1 votes
📚 BoredReading

You seem to be enjoying this.

Join free to unlock everything.

Create free account

Already have an account? Sign in