mcpField
D
dhan-tradehull

dhan-tradehull

github.com/imran-tradehull开发163 次安装15 周前更新
代码仓库

关于 dhan-tradehull

TradeHull 是 Dhan API 的 Python 封装;此技能为使用它编写交易策略和自动化程序提供参考。涵盖行情、期权、下单及投资组合操作,并给出认证、风控和部署指导。

主要功能

  1. 01三种认证模式
  2. 02行情及历史数据查询
  3. 03期权链与行权价选择
  4. 04订单创建、修改和取消
  5. 05持仓、余额与盈亏查询
  6. 06算法策略及部署指导

适用场景

  1. 01获取行情并计算交易信号
  2. 02编写含止损和目标价的日内策略
  3. 03设置跨交易日的 GTT 挂单
  4. 04查看持仓并配置盈亏退出

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/imran-tradehull/tradehull-dhan-live-algo-skills --skill dhan-tradehull

安装后在 Claude Code 中输入/dhan-tradehull确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

examples/
intraday_options_algo.py
nifty50_scanner_algo.py
positional_spread_algo.py
references/
algo-dev-workflow.md
algo-intraday-options.md
algo-positional-spread.md
algo-scanner.md
answer-patterns.md
auth.md
coding-style.md
common-patterns.md
deployment.md
dhanhq-raw.md
error-log.md
flask-ui.md
instruments.md
market-data.md
metadata.md
options.md
orders.md
portfolio.md
ui-ux.md
utilities.md

详细介绍

Dhan-Tradehull 技能(v3.3.2)

TradeHull 对 Dhan API 的 Python 封装。请务必先导入并初始化。

📐 生成代码时务必遵循 TradeHull 编码风格。 编写任何策略或算法代码前,请先阅读 references/coding-style.md。 关键规则:垂直对齐、bc1/bc2/sc1/sc2 条件、块注释、扁平结构。

参考文件 — 按需加载

任务阅读
登录、身份验证、令牌设置references/auth.md
LTP、OHLC、报价、历史数据references/market-data.md
期权链、行权价选择、过期数据references/options.md
下单、修改、取消、超级/永久订单references/orders.md
持仓、仓位、订单簿、余额、盈亏references/portfolio.md
手数、保证金、Telegram、盈亏退出、紧急停止开关references/utilities.md
错误、SEBI 法规、已知问题references/error-log.md
端到端构建算法(身份验证→数据→信号→订单→退出)references/algo-dev-workflow.md
扫描器:对观察列表扫描指标/交叉信号(TA-Lib)references/algo-scanner.md
基于算法的浏览器仪表盘 / UI(Flask)references/flask-ui.md
仪表盘设计:布局、颜色、进度、实时订单安全性references/ui-ux.md
在服务上运行算法:分离进程、重启、systemd、日志、端口references/deployment.md

1. 安装

pip install --pre dhanhq
pip install Dhan-Tradehull

2. 身份验证(3 种模式)

from Dhan_Tradehull import Tradehull

# Mode 1: Access Token
# ⚠️  TOKEN EXPIRES DAILY — must regenerate every morning before market open
# Get new token from: Dhan web → My Profile → API Access
tsl = Tradehull(client_code, token_id, mode="access_token")

# Mode 2: API Key (browser-based login flow)
tsl = Tradehull(client_code, mode="api_key", api_key=api_key, api_secret=api_secret)

# Mode 3: PIN + TOTP
# ✅ PIN IS VALID FOR LIFETIME — no daily regeneration needed
# Best for fully automated algos running without manual intervention
tsl = Tradehull(ClientCode=client_code, mode="pin_totp", pin=pin, totp_secret=totp_secret)

身份验证模式对比:

模式令牌有效期最适合
access_token⚠️ 每日 — 每天早晨重新生成手动/半自动交易
api_key每次都需通过浏览器流程一次性脚本
pin_totp✅ 永久有效(PIN 永不过期)全自动算法、计划任务

3. 市场数据

# LTP (Last Traded Price)
# ✅ Up to 500 symbols in one call, returns in under 1 second
# Returns dict → {symbol (str): ltp (float)}
data = tsl.get_ltp_data(names=['NIFTY', 'BANKNIFTY', 'CRUDEOIL'])
nifty_ltp = data['NIFTY']        # 24523.5
crude_ltp = data['CRUDEOIL']     # 6570.0

# Full Quote
data = tsl.get_quote_data(names=['RELIANCE'])

# OHLC
data = tsl.get_ohlc_data(names=['NIFTY', 'CRUDEOIL'])

# Historical Data (timeframe: '1','5','15','25','60','DAY')
df = tsl.get_historical_data(tradingsymbol='NIFTY', exchange='INDEX', timeframe='5')
df = tsl.get_historical_data(tradingsymbol='ACC', exchange='NSE', timeframe='1')

# Long-Term Historical (custom date range)
df = tsl.get_long_term_historical_data(
    tradingsymbol='RELIANCE', exchange='NSE', timeframe='5',
    from_date='2024-01-01', to_date='2025-01-01'
)

# Sector Data
df = tsl.get_historical_data(tradingsymbol="NIFTY 100", exchange="NSE",
                              timeframe="DAY", sector="YES")

交易所取值: 'NSE'、'BSE'、'NFO'、'BFO'、'MCX'、'INDEX'


4. 期权行权价选择

# ATM
CE_sym, PE_sym, strike = tsl.ATM_Strike_Selection(Underlying='NIFTY', Expiry=0)

# OTM (OTM_count = steps away from ATM)
CE_sym, PE_sym, CE_strike, PE_strike = tsl.OTM_Strike_Selection(
    Underlying='NIFTY', Expiry=0, OTM_count=5)

# ITM
CE_sym, PE_sym, CE_strike, PE_strike = tsl.ITM_Strike_Selection(
    Underlying='NIFTY', Expiry=0, ITM_count=1)

到期日: 0 = 当前周/月,1 = 下一个,2 = 更远期


5. 期权希腊值

⚠️ 实际上已弃用 — 请勿在新代码中使用 get_option_greek()。 Delta、Theta、Gamma、Vega、IV 等希腊值可直接通过 get_option_chain() 获取,该函数会返回包含每个行权价希腊值的完整 DataFrame。 获取希腊值数据时,请始终优先使用 get_option_chain()。


6. 期权链

# ✅ Returns TWO values — atm (int) + option_chain (DataFrame)
atm, chain = tsl.get_option_chain(Underlying="NIFTY", exchange="INDEX", expiry=0, num_strikes=10)

# atm = current ATM strike as int e.g. 24000
# chain = DataFrame, 21 rows × 27 columns (for num_strikes=10)

# Columns: CE OI, CE Chg in OI, CE Volume, CE IV, CE LTP,
#          CE Bid Qty, CE Bid, CE Ask, CE Ask Qty,
#          CE Delta, CE Theta, CE Gamma, CE Vega,
#          Strike Price,
#          PE Bid Qty, PE Bid, PE Ask, PE Ask Qty,
#          PE LTP, PE IV, PE Volume, PE Chg in OI, PE OI,
#          PE Delta, PE Theta, PE Gamma, PE Vega

# ATM row
atm_row      = chain[chain['Strike Price'] == atm]
ce_ltp       = atm_row['CE LTP'].values[0]
pe_ltp       = atm_row['PE LTP'].values[0]

# OI analysis
ce_resistance = chain.loc[chain['CE OI'].idxmax(), 'Strike Price']  # highest CE OI = resistance
pe_support    = chain.loc[chain['PE OI'].idxmax(), 'Strike Price']  # highest PE OI = support
pcr           = chain['PE OI'].sum() / chain['CE OI'].sum()         # Put-Call Ratio

# Exchange values
# INDEX  → NIFTY, BANKNIFTY, FINNIFTY
# MCX    → CRUDEOIL, GOLD, SILVER
# NFO    → stock options

✅ 包含希腊值 — 每个行权价的 Delta、Theta、Gamma、Vega、IV。 无需使用 get_option_greek() — 它已弃用。请改用此方法。


7. 下单

🚨 SEBI 法规(自 2026 年 4 月 1 日起生效) F&O 不再允许使用市价单。 所有订单都必须是限价单。

限价规则:

  • BUY → 限价必须高于 LTP(以便立即成交)
  • SELL → 限价必须低于 LTP(以便立即成交)

使用限价单即时成交的模式:

ltp = tsl.get_ltp_data(names=['NIFTY 19 DEC 24400 CALL'])['NIFTY 19 DEC 24400 CALL']
buy_price  = round(ltp * 1.02, 1)   # BUY 的价格高于 LTP 2%
sell_price = round(ltp * 0.98, 1)   # SELL 的价格低于 LTP 2%
# BUY limit order (price > LTP for instant fill)
order_id = tsl.order_placement(
    tradingsymbol='NIFTY 19 DEC 23300 CALL',
    exchange='NFO',
    quantity=75,
    price=0.05,               # must be > LTP
    trigger_price=0,
    order_type='LIMIT',       # ✅ always LIMIT — MARKET not allowed from Apr 2026
    transaction_type='BUY',
    trade_type='MIS'          # MIS, CNC, MARGIN, MTF, CO, BO
)

# SELL limit order (price < LTP for instant fill)
order_id = tsl.order_placement(
    tradingsymbol='NIFTY 19 DEC 23300 CALL',
    exchange='NFO',
    quantity=75,
    price=0.04,               # must be < LTP
    trigger_price=0,
    order_type='LIMIT',
    transaction_type='SELL',
    trade_type='MIS'
)

# Sliced/Iceberg order (exceeds freeze limit)
order_ids = tsl.order_placement(
    tradingsymbol="NIFTY 27 JAN 26000 CALL", exchange="NFO",
    transaction_type="BUY", quantity=1820, order_type="LIMIT",
    trade_type="MIS", price=21.05, should_slice=True
)
修改 / 取消
tsl.modify_order(order_id=orderid, order_type="LIMIT", quantity=50, price=0.1)
tsl.cancel_order(OrderID=orderid)
tsl.cancel_all_orders()  # Cancel all intraday + square off positions
订单信息
tsl.get_order_detail(orderid=orderid)
tsl.get_order_status(orderid=orderid)     # 'Pending', 'Completed', etc.
tsl.get_executed_price(orderid=orderid)
tsl.get_exchange_time(orderid=orderid)

8. 超级订单(一次性设置入场 + 目标价 + 止损)

✅ 算法策略首选的订单类型。 用户要求构建包含入场 + 止损 + 目标价的交易算法时, 请始终优先使用 place_super_order(),而不是分别下 3 个订单。 它通过一次调用即可处理完整的订单生命周期,并可选配追踪止损。

order_id = tsl.place_super_order(
    tradingsymbol="TRIDENT", exchange="NSE",
    transaction_type="BUY", quantity=1,
    order_type="LIMIT", trade_type="MIS",
    price=25, target_price=27,
    stop_loss_price=24, trailing_jump=0.2
)

# Modify specific leg: ENTRY_LEG, TARGET_LEG, STOP_LOSS_LEG
tsl.modify_super_order(order_id=order_id, order_type="LIMIT", quantity=1,
                        price=24.9, leg_name="ENTRY_LEG")

tsl.cancel_super_order(order_id=order_id, leg_name="STOP_LOSS_LEG")
super_orders = tsl.get_super_orders()

9. 永续订单 / GTT

✅ 适用于持仓策略的首选订单类型——波段交易、BTST、持仓交易。 当用户要求构建波段交易、BTST 或多日持仓算法时, 始终使用永续订单(GTT),而非普通订单。 永续订单会持续有效,跨越多个交易时段,直到触发或取消。

策略类型使用
日内交易,含止损 + 目标价place_super_order()
波段交易 / BTST / 持仓交易place_forever_order()
# SINGLE trigger — fires once when price condition met
forever_id = tsl.place_forever_order(
    tradingsymbol="TRIDENT", exchange="NSE",
    transaction_type="BUY", quantity=1,
    order_type="LIMIT", trade_type="CNC",
    price=25, trigger_price=25.05, order_flag="SINGLE"
)

# OCO — One Cancels Other (target + SL together)
forever_id = tsl.place_forever_order(
    tradingsymbol="TRIDENT", exchange="NSE",
    transaction_type="SELL", quantity=1,
    order_type="LIMIT", trade_type="CNC",
    price=27, trigger_price=27.05,          # target leg
    order_flag="OCO",
    quantity_1=1, price_1=24, trigger_price_1=23.95   # SL leg
)

# Modify a specific leg
tsl.modify_forever_order(
    order_id=forever_id, order_type="LIMIT",
    quantity=1, price=24.9, trigger_price=24.7,
    disclosed_quantity=0, validity="DAY",
    leg_name="STOP_LOSS_LEG", order_flag="SINGLE"
)

# Cancel
tsl.cancel_forever_order(order_id=forever_id)   # returns cancel order_id str

# Fetch all active forever orders
forever_orders = tsl.get_forever_orders()        # returns list

10. 条件触发订单

⚠️ TradeHull 策略中不使用。 我们使用 TA-Lib 计算指标,并直接在 Python 中检查条件。 这样可以完全控制指标参数、多条件逻辑 和自定义信号,比 Dhan 内置的触发条件灵活得多。

请勿在新代码中使用 place_conditional_trigger()。 请改用 get_historical_data() + TA-Lib。


11. 投资组合管理

holdings  = tsl.get_holdings()        # DataFrame
positions = tsl.get_positions()        # DataFrame
orderbook = tsl.get_orderbook()        # DataFrame
tradebook = tsl.get_trade_book()       # DataFrame
balance   = tsl.get_balance()          # float
pnl       = tsl.get_live_pnl()        # float

lot_size  = tsl.get_lot_size(tradingsymbol='NIFTY 19 DEC 24400 CALL')
# ⚠️ ALWAYS fetch lot size dynamically — never hardcode
# SEBI revises lot sizes periodically (e.g. NIFTY was 75, now 65)
# Hardcoded quantity causes order rejection when lot size changes

margin = tsl.margin_calculator(
    tradingsymbol='NIFTY DEC FUT', exchange='NFO',
    transaction_type='BUY', quantity=75,
    trade_type='MARGIN', price=24350, trigger_price=0
)

12. 完整市场深度(20 档)

# Single
depth_client = tsl.full_market_depth_data(("RELIANCE", "NSE"))
bid_df, ask_df = tsl.get_market_depth_df(depth_client)

# Multiple
symbol_list = [("RELIANCE","NSE"), ("NIFTY 09 DEC 26000 CALL","NFO")]
depth_data = tsl.full_market_depth_data(symbol_list)
for key, dc in depth_data.items():
    bid_df, ask_df = tsl.get_market_depth_df(dc)

13. 已到期期权历史数据

data = tsl.get_expired_option_data(
    tradingsymbol="NIFTY", exchange="NSE",
    interval=5,               # 1,5,15,25,60
    expiry_flag="WEEK",       # WEEK or MONTH
    expiry_code=1,            # 1=near, 2=next, 3=far
    strike="ATM",             # ATM, ATM+3, ATM-3 etc.
    option_type="CALL",
    from_date="2024-10-01", to_date="2024-10-31"
)

14. 基于盈亏的退出

# Auto exit when profit/loss threshold hit
tsl.enable_pnl_based_exit(
    profit_value=1000, loss_value=800,
    product_types=("INTRADAY", "DELIVERY"),
    enable_kill_switch=True   # True = full kill switch on trigger
)

15. Telegram 提醒

tsl.send_telegram_alert(
    message="BUY NIFTY 24400 CE @ 120 executed",
    receiver_chat_id="123456789",
    bot_token="YOUR_BOT_TOKEN"
)

📖 如果用户没有 receiver_chat_id 或 bot_token: 请引导他们访问 → https://tradehull.com/telegram-integration-for-algo-trading/


常见模式

OI 剥头皮循环框架
import time
from Dhan_Tradehull import Tradehull

tsl = Tradehull(client_code, token_id, mode="access_token")

while True:
    atm, chain = tsl.get_option_chain(Underlying="NIFTY", exchange="INDEX", expiry=0, num_strikes=5)
    # analyse chain for OI buildup / unwinding

    # place orders — always LIMIT for F&O (MARKET banned from Apr 2026)
    ce_name, pe_name, strike = tsl.ATM_Strike_Selection(Underlying="NIFTY", Expiry=0)
    ltp          = tsl.get_ltp_data(names=[ce_name])[ce_name]
    limit_price  = round(ltp * 1.02, 1)   # 2% above LTP for instant BUY fill
    order_id     = tsl.order_placement(
        tradingsymbol=ce_name, exchange="NFO", quantity=tsl.get_lot_size(ce_name),
        price=limit_price, trigger_price=0,
        order_type="LIMIT", transaction_type="BUY", trade_type="MIS"
    )
    time.sleep(1)
基于条件的入场(TradeHull 模式)
# Use TA-Lib to compute indicator, check condition in Python — not conditional trigger API
import talib

chart       = tsl.get_historical_data(tradingsymbol="RELIANCE", exchange="NSE", timeframe="15")
chart["rsi"] = talib.RSI(chart["close"], timeperiod=14)
rc           = chart.iloc[-1]   # last completed candle

bc1          = rc["rsi"] < 30   # oversold
bc2          = orderbook["RELIANCE"]["traded"] is None

if bc1 and bc2:
    ltp         = tsl.get_ltp_data(names=["RELIANCE"])["RELIANCE"]
    limit_price = round(ltp * 1.002, 1)
    order_id    = tsl.order_placement(
        tradingsymbol="RELIANCE", exchange="NSE", quantity=10,
        price=limit_price, trigger_price=0,
        order_type="LIMIT", transaction_type="BUY", trade_type="CNC"
    )

调试模式

在任何数据获取方法中添加 debug="YES",即可打印原始 API 响应:

data = tsl.get_ltp_data(names=['NIFTY'], debug="YES")

注释

  • access_token 每天过期——请在每天开盘前重新生成
  • pin_totp PIN 永久有效——适合完全自动化 / 定时运行的算法
  • 大数量订单超过交易所冻结限额时,设置 should_slice=True
  • 所有投资组合方法均返回 pd.DataFrame
  • 交易所取值:股票=NSE/BSE,指数=INDEX,F&O=NFO/BFO,大宗商品=MCX
  • 始终通过 get_lot_size() 动态获取合约手数——切勿硬编码
  • 最新版本:3.3.1(2026 年 6 月 3 日)

评论

支持 Markdown