feat: bandarmology (idx stocks bandar, analyze_bandar)

`idx stocks bandar SYMBOL...` reads the broker summary: for the top 1, 3,
5 and 10 brokers per side, buy value minus sell value in basis points of
value traded, with a signal from big accumulation to big distribution on
the headline tier (--top, default 5). Several symbols give a screen ranked
by that figure (at most 100, one request each), which pipes from
`stocks screen`. The MCP server exposes it as analyze_bandar (20 symbols).

- analysis/bandar.rs is pure and versioned (`top_concentration_v1`):
  integer basis points, no figure missing counted as zero, buy/sell VWAP
  from exact averages, and the brokers on both sides listed because their
  gross figures overstate their direction.
- Thresholds (±5%/±15%) follow fzn0x/idx (MIT); docs call them heuristics.
- Invalid input fails a screen at once; other errors fail one symbol and
  are warned about on stderr.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V3syn2fN2LNo5pvTSqc6eh
This commit is contained in:
hermes 2026-10-18 04:55:25 +00:00
commit 970da26a0e
25 changed files with 1588 additions and 37 deletions

View file

@ -0,0 +1,181 @@
<div id="modContentBrokerSum"></div>
<!--DATA BROKER SUMMARY-->
<div class="pa5">
<div class="row mincol-3">
<div class="col col-xs-5 col-sm-3">
<input class="form-control input-xs text-center" id="startDateBrokerSummary" name="startDate" placeholder="DD Month YYYY" value="10/16/2026" type="text">
</div>
<div class="col col-xs-5 col-sm-3">
<input class="form-control input-xs text-center" id="endDateBrokerSummary" name="endDate" placeholder="DD Month YYYY" value="10/16/2026" type="text">
</div>
<div class="mt15 visible-xs">&nbsp;</div>
<div class="col col-xs-5 col-sm-3">
<select class="form-control input-xs" id="FDBrokerSummary">
<option value="all">All</option>
<option value="F" >Foreign</option>
<option value="D" >Domestic</option>
</select>
</div>
<div class="col col-xs-5 col-sm-2">
<select class="form-control input-xs" id="boardBrokerSummary">
<option value="all">All Trade</option>
<option value="RG" >Regular</option>
<option value="TN" >Tunai</option>
<option value="NG" >Nego</option>
</select>
</div>
<div class="col col-xs-2 col-sm-1">
<button type="button" class="btn btn-default btn-block btn-xs-input" onClick="quickinfo_brokersummary($('#stockPageCode').val()!==undefined?$('#stockPageCode').val():$('#stockInfoCode').val(),$('#startDateBrokerSummary').val(),$('#endDateBrokerSummary').val(),$('#FDBrokerSummary').val(),$('#boardBrokerSummary').val());">GO</button>
</div>
</div>
</div>
<div class="table-responsive">
<table width="100%" border="0" cellspacing="0" cellpadding="0" class="table table-summary table-hover noborder nm">
<thead>
<tr>
<th align="center">Buyer</th>
<th align="right">B.Lot</th>
<th align="right">B.Val</th>
<th align="right">B.Avg</th>
<th align="center">#</th>
<th align="center">Seller</th>
<th align="right">S.Lot</th>
<th align="right">S.Val</th>
<th align="right">S.Avg</th>
</tr>
</thead>
<tbody>
<tr>
<td align="center"><span class="text-bumn">CC</span></td>
<td align="right"><span class="text-up">1.9 M</span></td>
<td align="right"><span class="text-up">504.3 B</span></td>
<td align="right"><span class="text-up">2,709 </span></td>
<td align="center">1</td>
<td align="center"><span class="text-foreign">AK</span></td>
<td align="right"><span class="text-down">3.7 M</span></td>
<td align="right"><span class="text-down">1.0 T</span></td>
<td align="right"><span class="text-down">2,716 </span></td>
</tr>
<tr>
<td align="center"><span class="text-local">XL</span></td>
<td align="right"><span class="text-up">1.6 M</span></td>
<td align="right"><span class="text-up">436.0 B</span></td>
<td align="right"><span class="text-up">2,720 </span></td>
<td align="center">2</td>
<td align="center"><span class="text-foreign">KZ</span></td>
<td align="right"><span class="text-down">1.8 M</span></td>
<td align="right"><span class="text-down">481.4 B</span></td>
<td align="right"><span class="text-down">2,672 </span></td>
</tr>
<tr>
<td align="center"><span class="text-foreign">AK</span></td>
<td align="right"><span class="text-up">1.2 M</span></td>
<td align="right"><span class="text-up">322.4 B</span></td>
<td align="right"><span class="text-up">2,719 </span></td>
<td align="center">3</td>
<td align="center"><span class="text-bumn">CC</span></td>
<td align="right"><span class="text-down">1.3 M</span></td>
<td align="right"><span class="text-down">358.2 B</span></td>
<td align="right"><span class="text-down">2,717 </span></td>
</tr>
<tr>
<td align="center"><span class="text-foreign">YP</span></td>
<td align="right"><span class="text-up">1.0 M</span></td>
<td align="right"><span class="text-up">281.3 B</span></td>
<td align="right"><span class="text-up">2,694 </span></td>
<td align="center">4</td>
<td align="center"><span class="text-foreign">BK</span></td>
<td align="right"><span class="text-down">933,299 </span></td>
<td align="right"><span class="text-down">253.5 B</span></td>
<td align="right"><span class="text-down">2,716 </span></td>
</tr>
<tr>
<td align="center"><span class="text-local">SQ</span></td>
<td align="right"><span class="text-up">712,722 </span></td>
<td align="right"><span class="text-up">193.1 B</span></td>
<td align="right"><span class="text-up">2,709 </span></td>
<td align="center">5</td>
<td align="center"><span class="text-local">XL</span></td>
<td align="right"><span class="text-down">697,845 </span></td>
<td align="right"><span class="text-down">189.9 B</span></td>
<td align="right"><span class="text-down">2,721 </span></td>
</tr>
<tr>
<td align="center"><span class="text-bumn">OD</span></td>
<td align="right"><span class="text-up">518,938 </span></td>
<td align="right"><span class="text-up">140.6 B</span></td>
<td align="right"><span class="text-up">2,709 </span></td>
<td align="center">6</td>
<td align="center"><span class="text-foreign">ZP</span></td>
<td align="right"><span class="text-down">477,399 </span></td>
<td align="right"><span class="text-down">129.4 B</span></td>
<td align="right"><span class="text-down">2,711 </span></td>
</tr>
<tr>
<td align="center"><span class="text-bumn">NI</span></td>
<td align="right"><span class="text-up">496,800 </span></td>
<td align="right"><span class="text-up">133.9 B</span></td>
<td align="right"><span class="text-up">2,695 </span></td>
<td align="center">7</td>
<td align="center"><span class="text-foreign">YU</span></td>
<td align="right"><span class="text-down">447,840 </span></td>
<td align="right"><span class="text-down">120.9 B</span></td>
<td align="right"><span class="text-down">2,700 </span></td>
</tr>
<tr>
<td align="center"><span class="text-foreign">YU</span></td>
<td align="right"><span class="text-up">420,264 </span></td>
<td align="right"><span class="text-up">112.3 B</span></td>
<td align="right"><span class="text-up">2,672 </span></td>
<td align="center">8</td>
<td align="center"><span class="text-foreign">YP</span></td>
<td align="right"><span class="text-down">431,663 </span></td>
<td align="right"><span class="text-down">117.6 B</span></td>
<td align="right"><span class="text-down">2,725 </span></td>
</tr>
<tr>
<td align="center"><span class="text-local">PD</span></td>
<td align="right"><span class="text-up">403,468 </span></td>
<td align="right"><span class="text-up">109.5 B</span></td>
<td align="right"><span class="text-up">2,713 </span></td>
<td align="center">9</td>
<td align="center"><span class="text-bumn">NI</span></td>
<td align="right"><span class="text-down">234,641 </span></td>
<td align="right"><span class="text-down">63.1 B</span></td>
<td align="right"><span class="text-down">2,690 </span></td>
</tr>
<tr>
<td align="center"><span class="text-local">XC</span></td>
<td align="right"><span class="text-up">381,871 </span></td>
<td align="right"><span class="text-up">103.7 B</span></td>
<td align="right"><span class="text-up">2,717 </span></td>
<td align="center">10</td>
<td align="center"><span class="text-local">XA</span></td>
<td align="right"><span class="text-down">217,888 </span></td>
<td align="right"><span class="text-down">59.1 B</span></td>
<td align="right"><span class="text-down">2,714 </span></td>
</tr>
</tbody>
<tfoot>
<tr class="bdr-t">
<th colspan="9" align="center">
<div class="text-center pt20 valign-middle" style="height:50px;">
<span class="fsize12 ml5 mr5">T. Val : 3.3 T</span>
<span class="fsize12 ml5 mr5">F. NVal : -1.1 T</span>
<span class="fsize12 ml5 mr5">T.Lot : 12.2 M</span>
<span class="fsize12 ml5 mr5">Avg : 2,708 </span>
</div>
</th>
</tr>
</tfoot>
</table>
</div>
<!-- =======================
======SCRIPT MODULE=========
============================-->
<script src="../../../../module/saham/include/js/data-brokersummary.js"></script>

View file

@ -0,0 +1,181 @@
<div id="modContentBrokerSum"></div>
<!--DATA BROKER SUMMARY-->
<div class="pa5">
<div class="row mincol-3">
<div class="col col-xs-5 col-sm-3">
<input class="form-control input-xs text-center" id="startDateBrokerSummary" name="startDate" placeholder="DD Month YYYY" value="10/16/2026" type="text">
</div>
<div class="col col-xs-5 col-sm-3">
<input class="form-control input-xs text-center" id="endDateBrokerSummary" name="endDate" placeholder="DD Month YYYY" value="10/16/2026" type="text">
</div>
<div class="mt15 visible-xs">&nbsp;</div>
<div class="col col-xs-5 col-sm-3">
<select class="form-control input-xs" id="FDBrokerSummary">
<option value="all">All</option>
<option value="F" >Foreign</option>
<option value="D" >Domestic</option>
</select>
</div>
<div class="col col-xs-5 col-sm-2">
<select class="form-control input-xs" id="boardBrokerSummary">
<option value="all">All Trade</option>
<option value="RG" >Regular</option>
<option value="TN" >Tunai</option>
<option value="NG" >Nego</option>
</select>
</div>
<div class="col col-xs-2 col-sm-1">
<button type="button" class="btn btn-default btn-block btn-xs-input" onClick="quickinfo_brokersummary($('#stockPageCode').val()!==undefined?$('#stockPageCode').val():$('#stockInfoCode').val(),$('#startDateBrokerSummary').val(),$('#endDateBrokerSummary').val(),$('#FDBrokerSummary').val(),$('#boardBrokerSummary').val());">GO</button>
</div>
</div>
</div>
<div class="table-responsive">
<table width="100%" border="0" cellspacing="0" cellpadding="0" class="table table-summary table-hover noborder nm">
<thead>
<tr>
<th align="center">Buyer</th>
<th align="right">B.Lot</th>
<th align="right">B.Val</th>
<th align="right">B.Avg</th>
<th align="center">#</th>
<th align="center">Seller</th>
<th align="right">S.Lot</th>
<th align="right">S.Val</th>
<th align="right">S.Avg</th>
</tr>
</thead>
<tbody>
<tr>
<td align="center"><span class="text-foreign">KZ</span></td>
<td align="right"><span class="text-up">1.9 M</span></td>
<td align="right"><span class="text-up">381.6 B</span></td>
<td align="right"><span class="text-up">1,960 </span></td>
<td align="center">1</td>
<td align="center"><span class="text-foreign">KZ</span></td>
<td align="right"><span class="text-down">3.7 M</span></td>
<td align="right"><span class="text-down">721.6 B</span></td>
<td align="right"><span class="text-down">1,933 </span></td>
</tr>
<tr>
<td align="center"><span class="text-bumn">CC</span></td>
<td align="right"><span class="text-up">1.5 M</span></td>
<td align="right"><span class="text-up">292.8 B</span></td>
<td align="right"><span class="text-up">1,932 </span></td>
<td align="center">2</td>
<td align="center"><span class="text-bumn">CC</span></td>
<td align="right"><span class="text-down">1.8 M</span></td>
<td align="right"><span class="text-down">353.9 B</span></td>
<td align="right"><span class="text-down">1,933 </span></td>
</tr>
<tr>
<td align="center"><span class="text-foreign">BK</span></td>
<td align="right"><span class="text-up">1.4 M</span></td>
<td align="right"><span class="text-up">274.7 B</span></td>
<td align="right"><span class="text-up">1,917 </span></td>
<td align="center">3</td>
<td align="center"><span class="text-foreign">BK</span></td>
<td align="right"><span class="text-down">1.6 M</span></td>
<td align="right"><span class="text-down">312.2 B</span></td>
<td align="right"><span class="text-down">1,926 </span></td>
</tr>
<tr>
<td align="center"><span class="text-foreign">RX</span></td>
<td align="right"><span class="text-up">1.0 M</span></td>
<td align="right"><span class="text-up">200.0 B</span></td>
<td align="right"><span class="text-up">1,933 </span></td>
<td align="center">4</td>
<td align="center"><span class="text-foreign">ZP</span></td>
<td align="right"><span class="text-down">1.0 M</span></td>
<td align="right"><span class="text-down">198.1 B</span></td>
<td align="right"><span class="text-down">1,926 </span></td>
</tr>
<tr>
<td align="center"><span class="text-foreign">ZP</span></td>
<td align="right"><span class="text-up">992,588 </span></td>
<td align="right"><span class="text-up">192.3 B</span></td>
<td align="right"><span class="text-up">1,937 </span></td>
<td align="center">5</td>
<td align="center"><span class="text-foreign">AK</span></td>
<td align="right"><span class="text-down">704,361 </span></td>
<td align="right"><span class="text-down">136.7 B</span></td>
<td align="right"><span class="text-down">1,941 </span></td>
</tr>
<tr>
<td align="center"><span class="text-foreign">YU</span></td>
<td align="right"><span class="text-up">944,581 </span></td>
<td align="right"><span class="text-up">180.4 B</span></td>
<td align="right"><span class="text-up">1,910 </span></td>
<td align="center">6</td>
<td align="center"><span class="text-local">MG</span></td>
<td align="right"><span class="text-down">529,257 </span></td>
<td align="right"><span class="text-down">101.4 B</span></td>
<td align="right"><span class="text-down">1,916 </span></td>
</tr>
<tr>
<td align="center"><span class="text-foreign">AK</span></td>
<td align="right"><span class="text-up">715,278 </span></td>
<td align="right"><span class="text-up">138.2 B</span></td>
<td align="right"><span class="text-up">1,932 </span></td>
<td align="center">7</td>
<td align="center"><span class="text-foreign">YU</span></td>
<td align="right"><span class="text-down">324,973 </span></td>
<td align="right"><span class="text-down">62.5 B</span></td>
<td align="right"><span class="text-down">1,924 </span></td>
</tr>
<tr>
<td align="center"><span class="text-local">MG</span></td>
<td align="right"><span class="text-up">528,650 </span></td>
<td align="right"><span class="text-up">100.6 B</span></td>
<td align="right"><span class="text-up">1,903 </span></td>
<td align="center">8</td>
<td align="center"><span class="text-bumn">NI</span></td>
<td align="right"><span class="text-down">208,165 </span></td>
<td align="right"><span class="text-down">39.8 B</span></td>
<td align="right"><span class="text-down">1,911 </span></td>
</tr>
<tr>
<td align="center"><span class="text-local">XL</span></td>
<td align="right"><span class="text-up">331,760 </span></td>
<td align="right"><span class="text-up">64.1 B</span></td>
<td align="right"><span class="text-up">1,931 </span></td>
<td align="center">9</td>
<td align="center"><span class="text-local">XL</span></td>
<td align="right"><span class="text-down">173,939 </span></td>
<td align="right"><span class="text-down">33.7 B</span></td>
<td align="right"><span class="text-down">1,937 </span></td>
</tr>
<tr>
<td align="center"><span class="text-foreign">YP</span></td>
<td align="right"><span class="text-up">234,664 </span></td>
<td align="right"><span class="text-up">44.9 B</span></td>
<td align="right"><span class="text-up">1,913 </span></td>
<td align="center">10</td>
<td align="center"><span class="text-foreign">YP</span></td>
<td align="right"><span class="text-down">168,848 </span></td>
<td align="right"><span class="text-down">32.7 B</span></td>
<td align="right"><span class="text-down">1,938 </span></td>
</tr>
</tbody>
<tfoot>
<tr class="bdr-t">
<th colspan="9" align="center">
<div class="text-center pt20 valign-middle" style="height:50px;">
<span class="fsize12 ml5 mr5">T. Val : 2.2 T</span>
<span class="fsize12 ml5 mr5">F. NVal : -90.2 B</span>
<span class="fsize12 ml5 mr5">T.Lot : 11.3 M</span>
<span class="fsize12 ml5 mr5">Avg : 1,931 </span>
</div>
</th>
</tr>
</tfoot>
</table>
</div>
<!-- =======================
======SCRIPT MODULE=========
============================-->
<script src="../../../../module/saham/include/js/data-brokersummary.js"></script>