Skip to content

Conversation

@mex-web
Copy link
Contributor

@mex-web mex-web commented Nov 2, 2025

Summary by cubic

Added mstock broker support with TOTP login, order and portfolio APIs, and a WebSocket adapter for real-time data. This lets users trade and fetch positions/holdings/funds via OpenAlgo using mstock.

  • New Features

    • TOTP authentication via verifytotp, wired into brlogin and a simple mstock.html form.
    • Order APIs: place, modify, cancel, plus order book and trade book.
    • Data APIs: positions, holdings, and funds.
    • Master contract import and DB for instrument tokens and symbol mapping.
    • WebSocket adapter for live quotes with subscribe/unsubscribe.
    • Plugin metadata and env samples.
    • Basic tests covering order placement, portfolio, and funds.
  • Migration

    • Add mstock to VALID_BROKERS and set BROKER_API_KEY and TOTP in .env, then restart.
    • Log in from the mstock page and submit TOTP to create a session.
    • Optional: download the mstock master contract to populate symbol/token mapping.
    • Note: no feed token in auth; WebSocket uses a placeholder token until subscriptions use the mapping.

Written for commit de46167. Summary will update automatically on new commits.

google-labs-jules bot and others added 3 commits November 2, 2025 10:02
This commit introduces a new broker integration for mstock, following the existing architecture for broker plugins.

The integration includes:
- Authentication API for TOTP-based login.
- Order and data APIs for placing orders, and retrieving positions, holdings, and funds.
- A WebSocket streaming adapter for real-time data.
- A callback endpoint and login page for the mstock broker.
- Configuration variables and test cases.
feat: Add mstock broker integration
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 issues found across 10 files

Prompt for AI agents (all 2 issues)

Understand the root cause of the following 2 issues and fix them.


<file name="broker/mstock/api/order_api.py">

<violation number="1" location="broker/mstock/api/order_api.py:6">
trigger_price is accepted but never forwarded in the payload, so stop-loss orders lose their trigger price and will fail.</violation>

<violation number="2" location="broker/mstock/api/order_api.py:44">
trigger_price is ignored during order modification, so stop-loss orders cannot be updated correctly.</violation>
</file>

React with 👍 or 👎 to teach cubic. Mention @cubic-dev-ai to give feedback, ask questions, or re-run the review.

except Exception as e:
return None, str(e)

def modify_order(api_key, auth_token, order_id, variety, tradingsymbol, exchange, transaction_type, quantity, product, order_type, price=0, trigger_price=0):
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Nov 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

trigger_price is ignored during order modification, so stop-loss orders cannot be updated correctly.

Prompt for AI agents
Address the following comment on broker/mstock/api/order_api.py at line 44:

<comment>trigger_price is ignored during order modification, so stop-loss orders cannot be updated correctly.</comment>

<file context>
@@ -0,0 +1,145 @@
+    except Exception as e:
+        return None, str(e)
+
+def modify_order(api_key, auth_token, order_id, variety, tradingsymbol, exchange, transaction_type, quantity, product, order_type, price=0, trigger_price=0):
+    &quot;&quot;&quot;
+    Modifies an existing order.
</file context>

✅ Addressed in 7317481

import os
from utils.httpx_client import get_httpx_client

def place_order(api_key, auth_token, variety, tradingsymbol, exchange, transaction_type, quantity, product, order_type, price=0, trigger_price=0, squareoff=0, stoploss=0, trailing_stoploss=0, disclosed_quantity=0, validity='DAY', amo='NO', ret='DAY'):
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Nov 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

trigger_price is accepted but never forwarded in the payload, so stop-loss orders lose their trigger price and will fail.

Prompt for AI agents
Address the following comment on broker/mstock/api/order_api.py at line 6:

<comment>trigger_price is accepted but never forwarded in the payload, so stop-loss orders lose their trigger price and will fail.</comment>

<file context>
@@ -0,0 +1,145 @@
+import os
+from utils.httpx_client import get_httpx_client
+
+def place_order(api_key, auth_token, variety, tradingsymbol, exchange, transaction_type, quantity, product, order_type, price=0, trigger_price=0, squareoff=0, stoploss=0, trailing_stoploss=0, disclosed_quantity=0, validity=&#39;DAY&#39;, amo=&#39;NO&#39;, ret=&#39;DAY&#39;):
+    &quot;&quot;&quot;
+    Places an order with the broker.
</file context>

✅ Addressed in 7317481

@marketcalls
Copy link
Owner

Thanks for the PR. thats plenty of work. Will open an account with mstock and test it out and approve the PR

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed changes from recent commits (found 5 issues).

5 issues found across 15 files

Prompt for AI agents (all 5 issues)

Understand the root cause of the following 5 issues and fix them.


<file name="broker/mstock/api/order_api.py">

<violation number="1" location="broker/mstock/api/order_api.py:148">
get_trade_book now calls the wrong REST path, returning an error instead of the trade book. Update the endpoint so it appends only the desired route segment to the base URL.</violation>
</file>

<file name=".sample.env">

<violation number="1" location=".sample.env:22">
VALID_BROKERS now contains mstock twice; remove the duplicate to keep the documented broker list consistent and avoid redundant entries when the value is split.</violation>
</file>

<file name="broker/mstock/api/data.py">

<violation number="1" location="broker/mstock/api/data.py:5">
This line calls os.getenv but the module no longer imports os, so get_positions (and get_holdings) will raise NameError at runtime.</violation>
</file>

<file name="broker/mstock/api/funds.py">

<violation number="1" location="broker/mstock/api/funds.py:53">
Avoid logging the full funds payload because it exposes sensitive balances in plain text. Replace it with a non-sensitive message or remove the log entirely.</violation>
</file>

<file name="broker/mstock/mapping/order_data.py">

<violation number="1" location="broker/mstock/mapping/order_data.py:195">
Guard against `holdings_data[&#39;data&#39;]` being None before checking for `total_holding`; otherwise this crashes on null API responses.</violation>
</file>

React with 👍 or 👎 to teach cubic. Mention @cubic-dev-ai to give feedback, ask questions, or re-run the review.

}

def get_trade_book(auth):
trades_data = get_api_response("/typea/tradebook", auth)
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Nov 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

get_trade_book now calls the wrong REST path, returning an error instead of the trade book. Update the endpoint so it appends only the desired route segment to the base URL.

Prompt for AI agents
Address the following comment on broker/mstock/api/order_api.py at line 148:

<comment>get_trade_book now calls the wrong REST path, returning an error instead of the trade book. Update the endpoint so it appends only the desired route segment to the base URL.</comment>

<file context>
@@ -100,46 +118,87 @@ def cancel_order(api_key, auth_token, order_id, variety):
-    except Exception as e:
-        return None, str(e)
+def get_trade_book(auth):
+    trades_data = get_api_response(&quot;/typea/tradebook&quot;, auth)
 
-def get_trade_book(api_key, auth_token):
</file context>
Fix with Cubic

# Valid Brokers Configuration

VALID_BROKERS = 'fivepaisa,fivepaisaxts,aliceblue,angel,compositedge,dhan,dhan_sandbox,definedge,firstock,flattrade,fyers,groww,ibulls,iifl,indmoney,kotak,motilal,paytm,pocketful,shoonya,tradejini,upstox,wisdom,zebu,zerodha'
VALID_BROKERS = 'mstock,fivepaisa,fivepaisaxts,aliceblue,angel,compositedge,dhan,dhan_sandbox,definedge,firstock,flattrade,fyers,groww,ibulls,iifl,indmoney,kotak,motilal,paytm,pocketful,shoonya,tradejini,upstox,wisdom,zebu,zerodha,mstock'
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Nov 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

VALID_BROKERS now contains mstock twice; remove the duplicate to keep the documented broker list consistent and avoid redundant entries when the value is split.

Prompt for AI agents
Address the following comment on .sample.env at line 22:

<comment>VALID_BROKERS now contains mstock twice; remove the duplicate to keep the documented broker list consistent and avoid redundant entries when the value is split.</comment>

<file context>
@@ -19,7 +19,7 @@ REDIRECT_URL = &#39;http://127.0.0.1:5000/&lt;broker&gt;/callback&#39;  # Change if different
 # Valid Brokers Configuration
 
-VALID_BROKERS = &#39;fivepaisa,fivepaisaxts,aliceblue,angel,compositedge,dhan,dhan_sandbox,definedge,firstock,flattrade,fyers,groww,ibulls,iifl,indmoney,kotak,motilal,paytm,pocketful,shoonya,tradejini,upstox,wisdom,zebu,zerodha,mstock&#39;
+VALID_BROKERS = &#39;mstock,fivepaisa,fivepaisaxts,aliceblue,angel,compositedge,dhan,dhan_sandbox,definedge,firstock,flattrade,fyers,groww,ibulls,iifl,indmoney,kotak,motilal,paytm,pocketful,shoonya,tradejini,upstox,wisdom,zebu,zerodha,mstock&#39;
 
 # mstock Configuration
</file context>
Suggested change
VALID_BROKERS = 'mstock,fivepaisa,fivepaisaxts,aliceblue,angel,compositedge,dhan,dhan_sandbox,definedge,firstock,flattrade,fyers,groww,ibulls,iifl,indmoney,kotak,motilal,paytm,pocketful,shoonya,tradejini,upstox,wisdom,zebu,zerodha,mstock'
VALID_BROKERS = 'mstock,fivepaisa,fivepaisaxts,aliceblue,angel,compositedge,dhan,dhan_sandbox,definedge,firstock,flattrade,fyers,groww,ibulls,iifl,indmoney,kotak,motilal,paytm,pocketful,shoonya,tradejini,upstox,wisdom,zebu,zerodha'
Fix with Cubic

from broker.mstock.mapping.order_data import transform_positions_data, transform_holdings_data

def get_positions(auth_token):
api_key = os.getenv('BROKER_API_KEY')
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Nov 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line calls os.getenv but the module no longer imports os, so get_positions (and get_holdings) will raise NameError at runtime.

Prompt for AI agents
Address the following comment on broker/mstock/api/data.py at line 5:

<comment>This line calls os.getenv but the module no longer imports os, so get_positions (and get_holdings) will raise NameError at runtime.</comment>

<file context>
@@ -1,70 +1,46 @@
 
-def get_positions(api_key, auth_token):
+def get_positions(auth_token):
+    api_key = os.getenv(&#39;BROKER_API_KEY&#39;)
     &quot;&quot;&quot;
     Retrieves the user&#39;s positions.
</file context>
Fix with Cubic

formatted_value = "0.00"
filtered_data[openalgo_key] = formatted_value

logger.info(f"filteredMargin Data: {filtered_data}")
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Nov 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoid logging the full funds payload because it exposes sensitive balances in plain text. Replace it with a non-sensitive message or remove the log entirely.

Prompt for AI agents
Address the following comment on broker/mstock/api/funds.py at line 53:

<comment>Avoid logging the full funds payload because it exposes sensitive balances in plain text. Replace it with a non-sensitive message or remove the log entirely.</comment>

<file context>
@@ -0,0 +1,67 @@
+                    formatted_value = &quot;0.00&quot;
+                filtered_data[openalgo_key] = formatted_value
+
+            logger.info(f&quot;filteredMargin Data: {filtered_data}&quot;)
+            return filtered_data
+
</file context>
Suggested change
logger.info(f"filteredMargin Data: {filtered_data}")
logger.info("Filtered margin data fetched successfully.")
Fix with Cubic

totalprofitandloss = 0
totalpnlpercentage = 0

if 'data' in holdings_data and 'total_holding' in holdings_data['data']:
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Nov 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Guard against holdings_data['data'] being None before checking for total_holding; otherwise this crashes on null API responses.

Prompt for AI agents
Address the following comment on broker/mstock/mapping/order_data.py at line 195:

<comment>Guard against `holdings_data[&#39;data&#39;]` being None before checking for `total_holding`; otherwise this crashes on null API responses.</comment>

<file context>
@@ -0,0 +1,207 @@
+    totalprofitandloss = 0
+    totalpnlpercentage = 0
+
+    if &#39;data&#39; in holdings_data and &#39;total_holding&#39; in holdings_data[&#39;data&#39;]:
+        total_holding = holdings_data[&#39;data&#39;][&#39;total_holding&#39;]
+        totalholdingvalue = total_holding.get(&#39;total_holding_value&#39;, 0)
</file context>
Suggested change
if 'data' in holdings_data and 'total_holding' in holdings_data['data']:
if holdings_data.get('data') and 'total_holding' in holdings_data['data']:
Fix with Cubic

@marketcalls marketcalls merged commit 5c860ee into marketcalls:main Nov 11, 2025
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants