<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Yash Lohade</title>
    <description>The latest articles on DEV Community by Yash Lohade (@lohadeyash).</description>
    <link>https://dev.to/lohadeyash</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1066354%2F2784bf75-addc-4924-b626-c2d1cd24328e.jpg</url>
      <title>DEV Community: Yash Lohade</title>
      <link>https://dev.to/lohadeyash</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/lohadeyash"/>
    <language>en</language>
    <item>
      <title>How I Debugged My AI Trading Agent Token Overflow, Memory Leaks &amp; Silent NaN Predictions</title>
      <dc:creator>Yash Lohade</dc:creator>
      <pubDate>Mon, 27 Jul 2026 06:56:39 +0000</pubDate>
      <link>https://dev.to/lohadeyash/how-i-debugged-my-ai-trading-agent-token-overflow-memory-leaks-silent-nan-predictions-9kg</link>
      <guid>https://dev.to/lohadeyash/how-i-debugged-my-ai-trading-agent-token-overflow-memory-leaks-silent-nan-predictions-9kg</guid>
      <description>&lt;h2&gt;
  
  
  Project Overview
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Algomaya&lt;/strong&gt; is an AI-powered algorithmic trading education platform I'm building solo. It lets users learn algo trading, build strategies with a no-code builder, backtest against historical data, and practice with paper trading — all powered by an AI agent called &lt;strong&gt;Maya&lt;/strong&gt; that autonomously chains together tools (backtests, signals, quotes, news) to answer complex trading questions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stack:&lt;/strong&gt; React Native (Expo SDK 54) + FastAPI + PostgreSQL + Groq LLM (Llama 3.3 70B) + LSTM neural network for price prediction&lt;/p&gt;

&lt;p&gt;The app has 89+ screens, 335+ commits, and a production backend on Google Cloud Run. It's a real product heading toward Play Store launch — which is exactly why these bugs mattered.&lt;/p&gt;




&lt;h2&gt;
  
  
  Bug Fix or Performance Improvement
&lt;/h2&gt;

&lt;p&gt;I fixed &lt;strong&gt;6 critical bugs&lt;/strong&gt; across the AI agent pipeline, LSTM prediction model, and frontend — the kind of bugs that silently corrupt data, leak memory, and crash production.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bug 1: AI Agent Token Overflow — Context Window Bomb
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;File:&lt;/strong&gt; &lt;code&gt;backend/app/services/maya_agent.py&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Maya's ReAct loop accumulates messages with every LLM call and tool result. Each tool response is truncated to 2000 chars, but with 15 max steps, the message array can balloon past Groq's context window limit. The result: &lt;code&gt;400 Bad Request&lt;/code&gt; errors that kill the agent mid-analysis, or worse — silently truncated context that makes the LLM hallucinate.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The fix — sliding window token management:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# BEFORE: Messages grew unbounded
&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;system&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;MAYA_SYSTEM_PROMPT&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;goal&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="c1"&gt;# ... messages.append() on every iteration, no limit check
&lt;/span&gt;
&lt;span class="c1"&gt;# AFTER: Token-aware trimming keeps context within budget
&lt;/span&gt;&lt;span class="nd"&gt;@staticmethod&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_estimate_token_count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Rough token estimate (~1.3 tokens per word).&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;1.3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nd"&gt;@staticmethod&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_trim_messages&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;max_tokens&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;6000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Keep system prompt + user goal + most recent messages within budget.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;MayaAgent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_estimate_token_count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;max_tokens&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;messages&lt;/span&gt;
    &lt;span class="c1"&gt;# Always preserve system prompt (index 0) and user goal (index 1)
&lt;/span&gt;    &lt;span class="n"&gt;trimmed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
    &lt;span class="n"&gt;remaining&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;
    &lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="n"&gt;budget&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;max_tokens&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;MayaAgent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_estimate_token_count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;trimmed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;reversed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;remaining&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;msg_tokens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;1.3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;budget&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;msg_tokens&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;
        &lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;budget&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="n"&gt;msg_tokens&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;trimmed&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;tail&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Impact:&lt;/strong&gt; Prevents context window overflow on complex multi-tool agent runs. The agent now gracefully drops older tool results while always preserving the system prompt and user's original goal.&lt;/p&gt;




&lt;h3&gt;
  
  
  Bug 2: Agent Run Hangs Indefinitely — No Outer Timeout
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;File:&lt;/strong&gt; &lt;code&gt;backend/app/services/maya_agent.py&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Each Groq API call has a 30s timeout, but the entire agent loop had &lt;strong&gt;no outer timeout&lt;/strong&gt;. If the LLM kept requesting tools in a loop (tool → LLM → tool → LLM...), the backend task could run for minutes or hours. The frontend times out at 30s, but the backend keeps burning CPU and API credits.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# BEFORE: No timeout guard on the loop
&lt;/span&gt;&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;step_number&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;max_steps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;_call_groq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;MAYA_TOOLS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# ... could run forever if LLM keeps calling tools
&lt;/span&gt;
&lt;span class="c1"&gt;# AFTER: Hard 5-minute timeout
&lt;/span&gt;&lt;span class="n"&gt;MAX_RUN_TIMEOUT_SECONDS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;

&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;step_number&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;max_steps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;elapsed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timezone&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;utc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;start_time&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;total_seconds&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;elapsed&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;MAX_RUN_TIMEOUT_SECONDS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;warning&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Maya run &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;run_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; exceeded &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;MAX_RUN_TIMEOUT_SECONDS&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;s timeout&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;summary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Analysis timed out. Please try a simpler query.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;completed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;
    &lt;span class="c1"&gt;# ... rest of loop
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Impact:&lt;/strong&gt; Prevents runaway agent executions from burning Groq API credits and Cloud Run CPU. Users get a clean timeout message instead of an infinite spinner.&lt;/p&gt;




&lt;h3&gt;
  
  
  Bug 3: Tool Result Truncation Destroys LLM Context
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;File:&lt;/strong&gt; &lt;code&gt;backend/app/services/maya_agent.py&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;When a backtest returns 500 trades, the old &lt;code&gt;_truncate_result()&lt;/code&gt; replaced the entire array with the string &lt;code&gt;"[500 items omitted]"&lt;/code&gt;. The LLM then received this useless string instead of actual data, making it impossible to analyze results properly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# BEFORE: Replace arrays with useless strings
&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;chart_data&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;trades&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;equity_curve&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;truncated&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;[&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; items omitted]&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;  &lt;span class="c1"&gt;# LLM can't parse this
&lt;/span&gt;
&lt;span class="c1"&gt;# AFTER: Keep first + last N items so LLM has real data to reason over
&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;trades&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;max_items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;truncated&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;  &lt;span class="c1"&gt;# First 5 + last 5 trades
&lt;/span&gt;        &lt;span class="n"&gt;truncated&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;_trades_total&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Total count for context
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Impact:&lt;/strong&gt; The LLM can now actually analyze backtest results — seeing both early and recent trades, real equity curve data points, and accurate totals. Before this fix, Maya would often say "I ran the backtest but can't see the results" because the data was replaced with placeholder strings.&lt;/p&gt;




&lt;h3&gt;
  
  
  Bug 4: LSTM Model Silently Predicts NaN — No Scaler Guards
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;File:&lt;/strong&gt; &lt;code&gt;backend/app/services/lstm_model.py&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The LSTM price prediction model's &lt;code&gt;_scale_sequences()&lt;/code&gt; and &lt;code&gt;predict()&lt;/code&gt; methods had zero protection against NaN/Inf values. When market data had gaps (common with Indian stocks on holidays), the scaler would produce NaN, the model would predict NaN, and the frontend would silently show "NEUTRAL" for every stock — with no error logged anywhere.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# BEFORE: No NaN protection — silent data corruption
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_scale_sequences&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;X_seq&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;flat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;X_seq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reshape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n_features&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;scaled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;scaler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;flat&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# NaN in → NaN out, silently
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;scaled&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reshape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n_samples&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;seq_len&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n_features&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# AFTER: Detect, log, and handle NaN at every stage
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_scale_sequences&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;X_seq&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;scaler&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Scaler not fitted. Call train() or load() first.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;flat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;X_seq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reshape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n_features&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isnan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;flat&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;warning&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Input contains NaN values before scaling — forward-filling&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;flat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;flat&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;ffill&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;fillna&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;values&lt;/span&gt;

    &lt;span class="n"&gt;scaled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;scaler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;flat&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isnan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scaled&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isinf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scaled&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;warning&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Scaling produced NaN/Inf — clamping to safe range&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;scaled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;nan_to_num&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scaled&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nan&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;posinf&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;3.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;neginf&lt;/span&gt;&lt;span class="o"&gt;=-&lt;/span&gt;&lt;span class="mf"&gt;3.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;scaled&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reshape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n_samples&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;seq_len&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n_features&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Impact:&lt;/strong&gt; Stock predictions no longer silently fail. NaN values from missing market data are forward-filled (a standard financial data technique), and extreme values that break the scaler are clamped to a safe range. Users now see actual predictions instead of blanket "NEUTRAL" signals.&lt;/p&gt;




&lt;h3&gt;
  
  
  Bug 5: TensorFlow Memory Leak in Prediction Loop
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;File:&lt;/strong&gt; &lt;code&gt;backend/app/services/lstm_model.py&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Every call to &lt;code&gt;predict()&lt;/code&gt; allocated &lt;code&gt;X_scaled&lt;/code&gt; and &lt;code&gt;X_seq&lt;/code&gt; numpy arrays but never cleaned them up. On Cloud Run with limited memory, repeated predictions (e.g., scanning 50 stocks for signals) would accumulate hundreds of MB of orphaned arrays until the container OOM-killed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# BEFORE: Arrays allocated, never freed
&lt;/span&gt;&lt;span class="n"&gt;X_scaled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;scaler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;X_seq&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_sequences_predict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;X_scaled&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;probabilities&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;predict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;X_seq&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;flatten&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="c1"&gt;# X_scaled and X_seq still in memory
&lt;/span&gt;
&lt;span class="c1"&gt;# AFTER: Explicit cleanup in finally block
&lt;/span&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;probabilities&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;predict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;X_seq&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;flatten&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;predictions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;probabilities&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;astype&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;finally&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;del&lt;/span&gt; &lt;span class="n"&gt;X_scaled&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;X_seq&lt;/span&gt;
    &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;gc&lt;/span&gt;
    &lt;span class="n"&gt;gc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;collect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Impact:&lt;/strong&gt; Prevents OOM crashes on Cloud Run during batch prediction operations. Memory is explicitly freed after each prediction call, keeping the container's footprint stable even when scanning dozens of stocks.&lt;/p&gt;




&lt;h3&gt;
  
  
  Bug 6: Sentry AI Agent Monitoring Integration
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;File:&lt;/strong&gt; &lt;code&gt;backend/app/services/maya_agent.py&lt;/code&gt;, &lt;code&gt;backend/app/main.py&lt;/code&gt;, &lt;code&gt;backend/app/core/config.py&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Beyond fixing bugs, I integrated &lt;strong&gt;Sentry&lt;/strong&gt; for full AI agent observability. Each Maya agent run now creates a Sentry transaction with spans for every LLM call and tool execution, complete with token usage tracking and error capture.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Sentry transaction wraps the entire agent run
&lt;/span&gt;&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;sentry_sdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start_transaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;op&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ai.agent&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;maya_agent_run&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;goal&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;txn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;txn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_tag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tier&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tier&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;txn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_tag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;run_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;run_id&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="c1"&gt;# Each LLM call gets its own span with token tracking
&lt;/span&gt;    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;sentry_sdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start_span&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;op&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ai.chat_completions.create&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;groq/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;GROQ_MODEL&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;llm_span&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;llm_span&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ai.model_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;GROQ_MODEL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;_call_groq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;MAYA_TOOLS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;usage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;usage&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt;
        &lt;span class="n"&gt;llm_span&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ai.prompt_tokens_used&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;usage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;prompt_tokens&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="n"&gt;llm_span&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ai.completion_tokens_used&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;usage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;completion_tokens&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="c1"&gt;# Each tool execution gets a span
&lt;/span&gt;    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;sentry_sdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start_span&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;op&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ai.tool&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;tool_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;tool_span&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;tool_span&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ai.tool.name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tool_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;_execute_tool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tool_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tool_args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tier&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;tier&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What this enables:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Conversation traces&lt;/strong&gt; — See the full agent reasoning chain (LLM call → tool → LLM → tool → summary) as a waterfall in Sentry&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Token usage monitoring&lt;/strong&gt; — Track prompt/completion tokens per run to detect context overflow before it happens&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tool failure tracking&lt;/strong&gt; — Pinpoint which tools fail most often and why&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance profiling&lt;/strong&gt; — Identify slow tool executions (backtests taking 10s+) vs fast ones (quotes &amp;lt;1s)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;

&lt;p&gt;All code changes are in the diffs above. Summary of files modified:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;File&lt;/th&gt;
&lt;th&gt;Change&lt;/th&gt;
&lt;th&gt;Impact&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;backend/app/services/maya_agent.py&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Token management, timeout guard, truncation fix, Sentry AI tracing&lt;/td&gt;
&lt;td&gt;Prevents crashes, hangs, and data loss in AI agent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;backend/app/services/lstm_model.py&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;NaN guards, memory cleanup&lt;/td&gt;
&lt;td&gt;Prevents silent prediction failures and OOM crashes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;backend/app/main.py&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Sentry SDK initialization&lt;/td&gt;
&lt;td&gt;Error tracking and performance monitoring&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;backend/app/core/config.py&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Sentry config variables&lt;/td&gt;
&lt;td&gt;Environment-specific monitoring config&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;backend/requirements.txt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Added&lt;code&gt;sentry-sdk[fastapi]&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Sentry dependency&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  My Improvements
&lt;/h2&gt;

&lt;p&gt;These fixes address the &lt;strong&gt;hardest class of bugs in AI applications&lt;/strong&gt; — the ones that don't crash loudly but silently corrupt your data pipeline:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Token overflow&lt;/strong&gt; was making Maya hallucinate on complex queries because the LLM lost context. The sliding window approach keeps the most recent tool results while always preserving the original goal.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The missing timeout&lt;/strong&gt; was burning real money — each Groq API call costs tokens, and a runaway agent could chain 15 calls over several minutes with no kill switch.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;NaN propagation&lt;/strong&gt; is the classic ML pipeline bug. One missing data point in market data → NaN features → NaN scaled values → NaN predictions → "NEUTRAL" everywhere. The fix adds guards at every stage of the pipeline.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Sentry integration&lt;/strong&gt; isn't just monitoring — it's &lt;strong&gt;AI agent observability&lt;/strong&gt;. Each agent run becomes a trace with spans for LLM calls and tool executions, token usage metrics, and error capture. This is exactly what you need to debug why an AI agent gave a bad answer.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;How I found them:&lt;/strong&gt; I conducted a systematic audit documenting 71 bugs across 4 severity levels. The AI pipeline bugs were the most dangerous because they failed silently — no crash, no error log, just wrong results served to users.&lt;/p&gt;




&lt;h2&gt;
  
  
  Best Use of Sentry
&lt;/h2&gt;

&lt;p&gt;I integrated &lt;strong&gt;Sentry&lt;/strong&gt; (&lt;code&gt;sentry-sdk[fastapi]&amp;gt;=2.10.0&lt;/code&gt;) into my FastAPI backend specifically for &lt;strong&gt;AI agent monitoring&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Setup:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Added &lt;code&gt;SENTRY_DSN&lt;/code&gt;, &lt;code&gt;SENTRY_TRACES_SAMPLE_RATE&lt;/code&gt;, and &lt;code&gt;SENTRY_PROFILES_SAMPLE_RATE&lt;/code&gt; to my Pydantic settings config&lt;/li&gt;
&lt;li&gt;Initialized Sentry in &lt;code&gt;main.py&lt;/code&gt; before middleware with &lt;code&gt;enable_tracing=True&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Used Sentry's AI-specific span operations (&lt;code&gt;ai.agent&lt;/code&gt;, &lt;code&gt;ai.chat_completions.create&lt;/code&gt;, &lt;code&gt;ai.tool&lt;/code&gt;) for proper categorization&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;How Sentry helps debug my AI agent:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Conversation Traces&lt;/strong&gt; — Each Maya agent run creates a Sentry transaction. I can see the full reasoning chain as a waterfall: which tools were called, how long each LLM call took, and where failures occurred.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Token Usage Tracking&lt;/strong&gt; — Every LLM span records &lt;code&gt;ai.prompt_tokens_used&lt;/code&gt; and &lt;code&gt;ai.completion_tokens_used&lt;/code&gt;. I can now detect token overflow &lt;em&gt;before&lt;/em&gt; it hits the context limit by monitoring token growth across runs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tool Failure Monitoring&lt;/strong&gt; — When a tool fails (e.g., Yahoo Finance API timeout), Sentry captures the exception with full context: which stock, which strategy, what the LLM was trying to do. This lets me prioritize which tool integrations need hardening.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance Profiling&lt;/strong&gt; — Sentry's continuous profiling shows that backtests are the bottleneck (5-15s per run), while stock quotes are fast (&amp;lt;500ms). This informed my decision to add the timeout guard — a 15-step run with 10 backtests could easily exceed 2 minutes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Error Alerting&lt;/strong&gt; — Sentry alerts on new error types. The first time I deployed, it immediately caught a &lt;code&gt;json.JSONDecodeError&lt;/code&gt; from malformed LLM tool arguments that I'd been silently swallowing as empty &lt;code&gt;{}&lt;/code&gt; — a bug I didn't even know existed.&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>devchallenge</category>
      <category>bugsmash</category>
    </item>
    <item>
      <title>I got tired of blowing up my trading account, so I built Algomaya 🇮🇳📈</title>
      <dc:creator>Yash Lohade</dc:creator>
      <pubDate>Mon, 20 Apr 2026 08:43:24 +0000</pubDate>
      <link>https://dev.to/lohadeyash/i-got-tired-of-blowing-up-my-trading-account-so-i-built-algomaya-1lce</link>
      <guid>https://dev.to/lohadeyash/i-got-tired-of-blowing-up-my-trading-account-so-i-built-algomaya-1lce</guid>
      <description>&lt;p&gt;Quick question before you scroll:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Have you ever had a "genius" trading idea at 2 AM, deployed it with real money the next morning, and then watched your capital disappear faster than your weekend plans?&lt;/strong&gt; 🫠&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Yeah. Same. That's literally why Algomaya exists.&lt;/p&gt;




&lt;h2&gt;
  
  
  The 2 AM moment that started it all
&lt;/h2&gt;

&lt;p&gt;I was sitting on my couch, chart open, convinced I had found &lt;em&gt;the&lt;/em&gt; pattern. You know the one, the setup that's going to change everything.&lt;/p&gt;

&lt;p&gt;I didn't paper trade it. I didn't backtest it. I just… sent it. 💸&lt;/p&gt;

&lt;p&gt;Spoiler: the pattern did not, in fact, change everything. (Well, it changed my P&amp;amp;L. Not in a good way.)&lt;/p&gt;

&lt;p&gt;That night I went looking for a tool where I could:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Test my strategy with &lt;strong&gt;real Indian market data&lt;/strong&gt; (NSE/BSE)&lt;/li&gt;
&lt;li&gt;Not spend 3 weekends configuring Python + broker APIs + data feeds&lt;/li&gt;
&lt;li&gt;Move from paper to live trading &lt;strong&gt;without rewriting everything&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Actually afford it as a retail trader 😅&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I couldn't find it. So I built it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Meet Algomaya 👋
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Algomaya&lt;/strong&gt; is an algo trading + paper trading platform built specifically for the Indian stock market.&lt;/p&gt;

&lt;p&gt;The core idea is stupidly simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Idea &amp;gt; Paper trade it &amp;gt; See if it actually works &amp;gt; Automate it &amp;gt; Sleep better
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No more "I think this strategy works." Either the numbers say yes, or they don't.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it does (in plain English)
&lt;/h2&gt;

&lt;p&gt;🧪 &lt;strong&gt;Paper Trading&lt;/strong&gt;: Run your strategies on live market data with zero risk. Your ego might take a hit, but your bank account won't.&lt;/p&gt;

&lt;p&gt;🤖 &lt;strong&gt;Algo Trading&lt;/strong&gt;: Once a strategy proves itself on paper, flip the switch and let it run automatically.&lt;/p&gt;

&lt;p&gt;🇮🇳 &lt;strong&gt;Built for India&lt;/strong&gt;: NSE, BSE, Indian brokers, Indian market hours, Indian quirks. Not a Robinhood clone with the logo changed.&lt;/p&gt;

&lt;p&gt;👨‍💻 &lt;strong&gt;Not just for quants&lt;/strong&gt;: You don't need to be a Python wizard or have a CFA to use it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The part where I need your help 🙏
&lt;/h2&gt;

&lt;p&gt;I'm building this in public, and honestly the best feedback comes from devs and traders who've been in the trenches. So I'd love your take on this:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;👉 Drop a comment and tell me:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Have you ever tried to automate your trading? What stopped you?&lt;/li&gt;
&lt;li&gt;If you trade Indian markets, what tool do you currently use, and what do you hate about it?&lt;/li&gt;
&lt;li&gt;What's the &lt;em&gt;one&lt;/em&gt; feature that would make you actually try a new trading platform?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I read every comment. Seriously. Even the spicy ones. 🌶️&lt;/p&gt;

&lt;h2&gt;
  
  
  Check it out
&lt;/h2&gt;

&lt;p&gt;🔗 &lt;strong&gt;&lt;a href="https://www.algomaya.com/" rel="noopener noreferrer"&gt;algomaya.com&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you're a fellow indie hacker / trader / dev curious about the fintech + India intersection, hit me up. Happy to nerd out about the tech stack, the regulatory maze, or how I'm thinking about the market.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;P.S. If this post saves even one person from their own 2 AM "genius idea," my work here is done.&lt;/em&gt; 😌&lt;/p&gt;

&lt;p&gt;Follow along for more build-in-public updates, the good, the bad, and the "why did I think this would be easy."&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>startup</category>
      <category>trading</category>
      <category>india</category>
    </item>
    <item>
      <title>I Built an AI-Powered Algo Trading App for the Indian Stock Market - Here's What I Learned</title>
      <dc:creator>Yash Lohade</dc:creator>
      <pubDate>Thu, 16 Apr 2026 19:10:43 +0000</pubDate>
      <link>https://dev.to/lohadeyash/i-built-an-ai-powered-algo-trading-app-for-the-indian-stock-market-heres-what-i-learned-ikd</link>
      <guid>https://dev.to/lohadeyash/i-built-an-ai-powered-algo-trading-app-for-the-indian-stock-market-heres-what-i-learned-ikd</guid>
      <description>&lt;p&gt;So, I've been quietly building something over the past year and I finally feel like it's time to talk about it openly. Not as a product pitch — more like a dev journal entry where I unpack what worked, what didn't, and what genuinely surprised me along the way.&lt;/p&gt;

&lt;p&gt;The app is called &lt;strong&gt;&lt;a href="https://algomaya.com" rel="noopener noreferrer"&gt;Algomaya&lt;/a&gt;&lt;/strong&gt; — a paper trading and algorithmic trading platform built specifically for the Indian stock market (NSE, NIFTY, BANKNIFTY, F&amp;amp;O). Check it out at &lt;strong&gt;&lt;a href="https://algomaya.com" rel="noopener noreferrer"&gt;algomaya.com&lt;/a&gt;&lt;/strong&gt; or download it directly: &lt;a href="https://play.google.com/store/apps/details?id=com.algomaya.app" rel="noopener noreferrer"&gt;Download Algomaya on Google Play&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Why I Built This
&lt;/h2&gt;

&lt;p&gt;I got into algo trading a few years back and quickly realized the Indian market had a weird gap. There were either super complex platforms meant for institutional traders, or overly simple apps that treated retail users like they couldn't handle real information. There was almost nothing in between for someone who actually wanted to &lt;em&gt;learn&lt;/em&gt; algorithmic trading without risking real money first.&lt;/p&gt;

&lt;p&gt;That's where the idea for &lt;strong&gt;Algomaya&lt;/strong&gt; came from — what if someone could practice trading with live market data, zero risk, and also &lt;em&gt;learn&lt;/em&gt; how to build trading strategies with AI assistance, all in one place?&lt;/p&gt;




&lt;h2&gt;
  
  
  What Algomaya Actually Does
&lt;/h2&gt;

&lt;p&gt;Here's a quick breakdown of the core features:&lt;/p&gt;

&lt;h3&gt;
  
  
  📈 Paper Trading &amp;amp; Virtual Trading Simulator (FREE)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Real-time NSE/BSE market data during live market hours (9:15 AM – 3:30 PM)&lt;/li&gt;
&lt;li&gt;Trade NSE stocks, NIFTY, BANKNIFTY, FinNIFTY, and F&amp;amp;O options with virtual cash&lt;/li&gt;
&lt;li&gt;Full simulated P&amp;amp;L tracking, trade history, virtual portfolio management&lt;/li&gt;
&lt;li&gt;No real money involved — zero risk, full market realism&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  🤖 No-Code Algo Trading Platform
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Build and backtest trading strategies without writing a single line of code&lt;/li&gt;
&lt;li&gt;AI-powered strategy builder using natural language — describe what you want, it builds the logic&lt;/li&gt;
&lt;li&gt;Deploy strategies to paper trade automatically during live market hours&lt;/li&gt;
&lt;li&gt;11+ free algorithmic trading courses built right into the app&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  💬 AI Trading Assistant
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Ask questions, get real-time market analysis and strategy suggestions&lt;/li&gt;
&lt;li&gt;Helps beginners understand concepts like moving averages, RSI, Bollinger Bands&lt;/li&gt;
&lt;li&gt;Think of it like a knowledgeable trading buddy that's always available&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🔗 &lt;strong&gt;&lt;a href="https://play.google.com/store/apps/details?id=com.algomaya.app" rel="noopener noreferrer"&gt;Try Algomaya FREE on Google Play&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The Technical Stack (The Part I Actually Want to Talk About)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Choosing the Right Stack
&lt;/h3&gt;

&lt;p&gt;For an Android app dealing with live financial data, performance and reliability are non-negotiable. Here's what I landed on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Kotlin&lt;/strong&gt; for the Android frontend — coroutines saved my life when handling real-time data streams&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Python&lt;/strong&gt; backend for the AI and strategy execution engine&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;WebSockets&lt;/strong&gt; for live market data feeds — REST APIs just don't cut it for tick-by-tick data&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Firebase&lt;/strong&gt; for auth and real-time sync&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TensorFlow Lite&lt;/strong&gt; on-device for latency-sensitive AI inference&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The hardest part? Keeping the live data pipeline stable. NSE data feeds can be... temperamental. Building retry logic, fallback mechanisms, and graceful degradation was probably 30% of the total dev time.&lt;/p&gt;

&lt;h3&gt;
  
  
  Building the No-Code Strategy Builder
&lt;/h3&gt;

&lt;p&gt;This was the most interesting engineering challenge. The goal: let a user describe a strategy in plain English and turn it into executable trading logic.&lt;/p&gt;

&lt;p&gt;The approach I landed on:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;User inputs a strategy description (e.g., &lt;em&gt;"Buy when RSI crosses above 30 and price is above 200 EMA"&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;An LLM parses this into a structured strategy schema (conditions, entry/exit rules, indicators)&lt;/li&gt;
&lt;li&gt;The schema compiles into a backtesting engine that runs against historical NSE data&lt;/li&gt;
&lt;li&gt;User sees backtest results and can deploy to live paper trading&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Getting step 2 right took &lt;em&gt;way&lt;/em&gt; longer than expected. LLMs are great at understanding intent but they hallucinate indicator parameters constantly. I ended up building a validation layer that catches impossible or contradictory conditions before they hit the backtesting engine.&lt;/p&gt;

&lt;h3&gt;
  
  
  The AI Integration Layer
&lt;/h3&gt;

&lt;p&gt;I used a combination of fine-tuned models and &lt;strong&gt;RAG (Retrieval Augmented Generation)&lt;/strong&gt; for the trading assistant. The knowledge base includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SEBI regulations and guidelines&lt;/li&gt;
&lt;li&gt;NSE/BSE trading rules and circuit breakers&lt;/li&gt;
&lt;li&gt;Technical analysis documentation&lt;/li&gt;
&lt;li&gt;Historical market patterns specific to Indian indices&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One thing I learned the hard way: &lt;strong&gt;generic AI models trained on Western market data give terrible advice for Indian markets.&lt;/strong&gt; NIFTY and BANKNIFTY behave very differently from S&amp;amp;P 500 constituents. The fine-tuning step was absolutely essential.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I Got Wrong (Being Honest With Yourself)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. I Underestimated Onboarding Complexity
&lt;/h3&gt;

&lt;p&gt;Most early users were complete beginners. The UI I built assumed people knew what "F&amp;amp;O" or "BANKNIFTY" meant. Spoiler: they didn't. I had to rebuild a significant portion of the onboarding flow with progressive disclosure — start simple, layer in complexity.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. The Backtesting Engine Was Too Optimistic
&lt;/h3&gt;

&lt;p&gt;Early backtest results looked great. Almost suspiciously great. The issue was &lt;strong&gt;lookahead bias&lt;/strong&gt; — I was accidentally allowing the strategy to "see" future data during backtesting. Classic mistake. Fixing it required a full rewrite of the data pipeline.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. I Shipped Too Many Features at Once
&lt;/h3&gt;

&lt;p&gt;Classic developer mistake. I thought more features = better app. Users thought it = confusing app. The current version is much more focused. When in doubt, cut.&lt;/p&gt;




&lt;h2&gt;
  
  
  AI Trends That Actually Matter for Fintech Apps Right Now
&lt;/h2&gt;

&lt;p&gt;Since this post is partly about AI development, here's what I've found genuinely useful in the &lt;strong&gt;#GenerativeAI&lt;/strong&gt; and &lt;strong&gt;#AIAgents&lt;/strong&gt; space for fintech:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;RAG over fine-tuning for domain knowledge&lt;/strong&gt; — unless you have massive labeled datasets, RAG is more practical and easier to update&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Structured output from LLMs&lt;/strong&gt; — tools like function calling in the OpenAI API are game changers for reliable parsing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;On-device ML for latency-sensitive features&lt;/strong&gt; — TFLite for Android is underrated; it also keeps sensitive financial data off the cloud&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Embeddings for pattern similarity&lt;/strong&gt; — finding similar historical market patterns using vector search is genuinely powerful&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Where Algomaya Is Headed
&lt;/h2&gt;

&lt;p&gt;The roadmap includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Options strategy visualization&lt;/li&gt;
&lt;li&gt;Multi-leg strategy builder&lt;/li&gt;
&lt;li&gt;Community where traders can share and fork strategies&lt;/li&gt;
&lt;li&gt;More conversational and context-aware AI assistant across sessions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're building in the &lt;strong&gt;fintech + AI&lt;/strong&gt; space in India, or you're a developer interested in algo trading, I'd genuinely love to connect and talk shop.&lt;/p&gt;




&lt;h2&gt;
  
  
  Resources &amp;amp; Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;🌐 &lt;strong&gt;&lt;a href="https://algomaya.com" rel="noopener noreferrer"&gt;Algomaya Official Website&lt;/a&gt;&lt;/strong&gt; — Learn more about the platform&lt;/li&gt;
&lt;li&gt;🚀 &lt;strong&gt;&lt;a href="https://play.google.com/store/apps/details?id=com.algomaya.app" rel="noopener noreferrer"&gt;Download Algomaya — FREE Paper &amp;amp; Algo Trading App&lt;/a&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;📚 &lt;strong&gt;&lt;a href="https://play.google.com/store/apps/details?id=com.algomaya.app" rel="noopener noreferrer"&gt;Learn Algorithmic Trading — 11+ Free Courses on Algomaya&lt;/a&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;📖 &lt;a href="https://www.investopedia.com/terms/p/papertrade.asp" rel="noopener noreferrer"&gt;What is Paper Trading? (Investopedia)&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;📊 &lt;a href="https://www.nseindia.com" rel="noopener noreferrer"&gt;NSE India — Official Market Data&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🤖 &lt;a href="https://python.langchain.com/docs/tutorials/rag/" rel="noopener noreferrer"&gt;LangChain RAG Documentation&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;If you've built something similar or have thoughts on AI + trading, drop a comment below. Always happy to geek out about this stuff.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; #AI #MachineLearning #GenerativeAI #AIAgents #LLM #FinTech #AlgoTrading #AndroidDev #MobileDev #IndianStockMarket #PaperTrading #NoCode #RAG #TensorFlow #Kotlin #BuildInPublic #100DaysOfCode #StockMarket #DevJournal #OpenSource&lt;/p&gt;

</description>
      <category>ai</category>
      <category>android</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
