Skip to content

Latest commit

 

History

History
212 lines (186 loc) · 10.2 KB

File metadata and controls

212 lines (186 loc) · 10.2 KB

BanTA 技术分析库

banta是一个高性能的技术分析指标库,支持状态缓存/并行计算两种模式。旨在提供高自由度、高性能、简洁易用的指标框架。

DeepWiki问答

  • 状态缓存模式: 在每个K线上更新并缓存,无需重新计算历史数据,指标计算结果全局重用;类似TradingView
  • 并行计算模式: 一次性计算所有K线,无缓存,收到新K线需再次重新计算;类似ta-lib
  • nan值兼容: 智能忽略输入数据中间的nan值,后续计算继续使用之前的状态
  • 严格测试: 每个指标都使用各种条件单元测试验证,并和常见指标库结果对比
  • 轻量无依赖: 仅使用golang,无任何依赖包
  • 支持python: 已通过gopy打包为bbta包,可直接从python中导入使用

支持的指标

和常见指标平台结果一致性对比

banta MyTT TA-lib Class TA-lib Metastock Pandas-TA TradingView
AvgPrice
Sum
SMA T1
EMA T1 T1 T2
EMABy1 T1 T2 T2 T3
RMA -- -- -- T1 --
VWMA -- -- --
WMA
HMA -- -- --
TR -- --
ATR T1 T2 T3
MACD T1 T2 T1 T3
RSI T1 T2 T3
KDJ T1 T2 T1 T3
Stoch -- --
BBANDS
Aroon -- T1
ADX -- T1 T2
ADXBy1 -- T1 T1 T2
PluMinDI -- -- --
PluMinDM -- -- --
ROC --
TNR/ER -- -- -- -- --
CCI
CMF -- -- --
KAMA -- T1 ✔~
WillR --
StochRSI -- ✔~
MFI
RMI -- -- -- -- ✔~
CTI -- -- -- T1
LinReg -- -- -- ?
CMO -- T1
CMOBy1 -- T1 T1 T1
CHOP -- -- -- T1
ALMA -- -- -- T1
Stiffness -- -- -- --
PercentRank -- -- -- -- ✔~
CRSI -- -- -- -- ✔~
CRSIBy1 -- community -- -- --
DV -- -- -- -- --
UTBot -- -- -- --
STC -- -- -- --
-- 此平台没有该指标
✔  和此平台计算结果一致
✔~ 和此平台计算结果基本一致(有一定偏差)
Ti  和此平台计算结果不一致 

如何使用(带状态缓存)

import (
	"fmt"
	ta "github.com/banbox/banta"
)

var envMap = make(map[string]*ta.BarEnv)

func OnBar(symbol string, timeframe string, bar *ta.Kline) {
	envKey := fmt.Sprintf("%s_%s", symbol, timeframe)
	e, ok := envMap[envKey]
	if !ok {
		e = &ta.BarEnv{
			TimeFrame: timeframe,
			BarNum:    1,
		}
		envMap[envKey] = e
	}
	e.OnBar(bar.Time, bar.Open, bar.High, bar.Low, bar.Close, bar.Volume, bar.Quote, bar.BuyVolume, bar.TradeNum)
	ma5 := ta.SMA(e.Close, 5)
	ma30 := ta.SMA(e.Close, 30)
	atr := ta.ATR(e.High, e.Low, e.Close, 14).Get(0)
	xnum := ta.Cross(ma5, ma30)
	if xnum == 1 {
		// ma5 cross up ma30
		curPrice := e.Close.Get(0) // or bar.Close
		stopLoss := curPrice - atr
		fmt.Printf("open long at %f, stoploss: %f", curPrice, stopLoss)
	} else if xnum == -1 {
		// ma5 cross down ma30
		curPrice := e.Close.Get(0)
		fmt.Printf("close long at %f", curPrice)
	}
	kdjRes := ta.KDJ(e.High, e.Low, e.Close, 9, 3, 3).Cols
	k, d := kdjRes[0], kdjRes[1]
}

核心理念

传统的技术分析库比如ta-libpandas-ta这些库非常流行,也进行了很多性能优化,在一次性计算几百上千跟K线时速度非常快。
但在你的机器人实盘运行使用这些库时,每次收到新的K线都要同时传入前面几百个K线数据,如果运行的标的更多一些,或者如果在1m甚至1s上运行时,计算延迟就会大到无法忍受。
很多人都用过TradingView,它使用的PineScript就是一个基于事件的技术分析引擎;它不会在收到一根新K线时重新运行前面的K线,而是使用前面缓存的结果。
这也是BanTA的设计理念,基于事件,每收到一个K线运行一次,使用前面缓存的结果。

BanTA中状态缓存是如何实现的

BanTA中,状态缓存的核心是Series序列类型,基本上所有返回值都是序列,Series中有Data []float64字段,它记录了当前指标在每个K线的值。
最常用的e.Close就是收盘价序列,e.Close.Get(0)就是float64类型的当前收盘价;
计算均值也很简单:ma5 := ta.SMA(e.Close, 5),返回的ma5也是一个序列;
有些指标如KDJ一般返回k和d两个字段kdjRes := ta.KDJ(e.High, e.Low, e.Close, 9, 3, 3).Cols,可以从Cols中得到两个序列组成的数组。

如何使用(并行计算)

import (
	"github.com/banbox/banta/tav"
)

func main(){
	highArr := []float64{1.01, 1.01, 1.02, 0.996, 0.98, 0.993, 0.99, 1.0, 1.02}
    lowArr := []float64{0.99, 1.0, 1.0, 0.98, 0.965, 0.98, 0.98, 0.984, 1.0}
	closeArr := []float64{1.0, 1.01, 1.0, 0.99, 0.97, 0.981, 0.988, 0.992, 1.002}
	sma := tav.SMA(closeArr, 5)
    ma30 := tav.SMA(closeArr, 30)
    atr := tav.ATR(highArr, lowArr, closeArr, 14)
    xArr := tav.Cross(ma5, ma30)
	
}

提示

建议您在进行研究时使用并行计算一次性获取指标计算结果,在实盘或基于事件驱动回测时使用带状态指标,效率更高。

Python安装

pip install bbta

仅支持python8及以上版本,暂不支持macos和windows下python13

Python使用带状态指标

from bbta import ta

# 1. 创建环境
# BarEnv 用于管理状态,在每个时间周期/交易对上创建一个即可
env = ta.BarEnv(TimeFrame="1m")

# 2. 准备K线数据
# (时间戳ms, 开, 高, 低, 收, 交易量)
klines = [
    (1672531200000, 100, 102, 99, 101, 1000), (1672531260000, 101, 103, 100, 102, 1200),
    (1672531320000, 102, 105, 101, 104, 1500), (1672531380000, 104, 105, 103, 103, 1300),
    (1672531440000, 103, 104, 102, 103, 1100), (1672531500000, 103, 106, 103, 105, 1600),
    (1672531560000, 105, 107, 104, 106, 1800), (1672531620000, 106, 106, 102, 103, 2000),
    (1672531680000, 103, 104, 101, 102, 1700), (1672531740000, 102, 103, 100, 101, 1400),
]

# 3. 模拟K线推送
# 在实盘中,每收到一根新K线就调用一次 OnBar
for kline in klines:
    ts, o, h, l, c, v = kline
    env.OnBar(ts, o, h, l, c, v, 0, 0, 0)

    # 4. 计算指标
    ma5 = ta.Series(ta.SMA(env.Close, 5))
    ma30 = ta.Series(ta.SMA(env.Close, 30))

    # 获取最新值
    ma5_val = ma5.Get(0)
    ma30_val = ma30.Get(0)
    print(f"Close={c:.2f}, MA5={ma5_val:.2f}, MA30={ma30_val:.2f}")

Python使用并行计算指标

from bbta import tav, go

# 1. 准备数据
# 并行计算模式的函数接收 go.Slice_float64 类型
# 我们可以从python list创建
high_py = [102.0, 103.0, 105.0, 105.0, 104.0, 106.0, 107.0, 106.0, 104.0, 103.0]
low_py = [99.0, 100.0, 101.0, 103.0, 102.0, 103.0, 104.0, 102.0, 101.0, 100.0]
close_py = [101.0, 102.0, 104.0, 103.0, 103.0, 105.0, 106.0, 103.0, 102.0, 101.0]

high = go.Slice_float64(high_py)
low = go.Slice_float64(low_py)
close = go.Slice_float64(close_py)

# 2. 一次性计算所有指标
# 返回结果也是 go.Slice 类型
ma5 = tav.SMA(close, 5)
atr = tav.ATR(high, low, close, 14)

# 3. 查看结果
# 可以转为python list查看
print(f"Close: {list(close)[-5:]}")
print(f"MA5:   {[f'{x:.2f}' for x in list(ma5)[-5:]]}")
print(f"ATR:   {[f'{x:.2f}' for x in list(atr)[-5:]]}")

# 对于多返回值指标,比如KDJ
kdj_result = tav.KDJ(high, low, close, 9, 3, 3)
k_line = kdj_result[0]
d_line = kdj_result[1]
j_line = kdj_result[2]
print(f"K-line: {[f'{x:.2f}' for x in list(k_line)[-5:]]}")