Ricequant 開源算法交易回測框架RQAlpha

rqalpha
rqalpha

項目地址:https://github.com/ricequant/rqalpha/

RQAlpha

簡介

RQAlpha是一個開源的Python算法交易和回測引擎,適合A股市場,是事件驅動的設計。自帶日線數據, 目前暫時僅支持日線回測。

RQAlpha的邏輯也將會在Ricequant的一些回測部分使用,Ricequant - 是一個開放的量化算法交易社區,有免費的服務器資源給大家測試、實盤模擬您的交易算法,并且可以將交易信號通過微信和郵件實時推送給大家, 如果您想要更好的回測報告體驗和實盤模擬交易功能可以把本地寫好的策略復制黏貼到我們的網站上運行。

如果您想參與和貢獻進來這個項目,可以發郵件給 public@ricequant.com 聯系,如果您有功能需求或者bug報告的話,都可以開一個issue:

https://github.com/ricequant/rqalpha/issues

特色

  • 容易使用:RQAlpha可以讓你集中精力在策略的開發上。可以參考./examples 下的范例
  • 需要傳入歷史數據,計算的結果是pandas的DataFrame, 和PyData的生態系統很好的結合在一起
  • 可以使用Python的統計、機器學習等科學計算庫如matplotlib, scipy, statsmodels和sklearn等
  • 免費提供了Ricequant的日級別數據,可以通過互聯網自己更新data bundle

安裝

# 為了避免一些安裝問題,請先升級您的pip和setuptools
pip install -U pip setuptools

# 安裝rqalpha
pip install rqalpha

# 升級rqalpha
pip install -U rqalpha

# 國內的用戶們可以使用鏡像
pip install -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com -U rqalpha

For Windows用戶

如果出現缺失cl.exe,請訪問https://wiki.python.org/moin/WindowsCompilers下載VC并且安裝。

如果在安裝bcloz出現編譯困難,可以從bcolz下載bcolz安裝,安裝bcloz后,再安裝rqalpha

安裝依賴

安裝TA-Lib

你可以通過PyPI安裝:

$ pip install TA-Lib

如果發現無法通過 pip 安裝,請訪問 https://mrjbq7.github.io/ta-lib/install.html 解決。

對于Windows用戶,如果編譯困難,可以根據您本地的Python版本下載指定版本的whl包,然后pip install TA_Lib-0.4.9-cp27-none-win_amd64.whl

Usage

Usage: rqalpha [OPTIONS] COMMAND [ARGS]...

Options:
  -v, --verbose
  --help         Show this message and exit.

Commands:
  examples       generate example strategies to target folder
  plot           draw result DataFrame
  run            run strategy from file
  update_bundle  update data bundle, download if not found

下載回測需要的數據bundle

運行以下命令,將會從Ricequant的服務器下載最新的日級別數據,為回測提供數據支持。

rqalpha update_bundle

生成樣例策略

運行以下命令,將會在指定目錄生成一個examples文件夾,其中包含幾個有趣的樣例策略。

rqalpha examples -d ./

運行回測

回測腳本參數如下:

Usage: rqalpha run [OPTIONS]

  run strategy from file

Options:
  -f, --strategy-file PATH     [required]
  -s, --start-date DATE        [required]
  -e, --end-date DATE          [required]
  -o, --output-file PATH
  -i, --init-cash INTEGER
  --plot / --no-plot           plot result
  --progress / --no-progress   show progress bar
  -d, --data-bundle-path PATH
  --help                       Show this message and exit.

運行以下命令,將開始回測

rqalpha run -f examples/multi_rsi.py -s 2014-01-01 -e 2016-01-01 -o result.pkl --plot

等待回測結束后,將顯示您的收益率和Risk。

backtest
backtest

繪制回測結果

如果運行完回測后,還需要再次繪制回測結果,可以運行以下命令:

rqalpha plot result.pkl

分析結果

RQAlpha可以輸出一個DataFrame,其中包含了每天的Portfolio信息、Risk信息、Trades和Positions。

其Index是交易日,columns包括alpha, annualized_returns, benchmark_annualized_returns, benchmark_daily_returns, benchmark_total_returns, beta, cash, daily_returns, downside_risk, information_rate, market_value, max_drawdown, pnl, portfolio_value, positions, sharpe, sortino, total_commission, total_returns, total_tax, tracking_error, trades, volatility

其中positions是當日的持倉信息,trades是當日的交易信息。

import pandas as pd
df = pd.read_pickle("result.pkl")
print(df.iloc[-1])

'''
alpha                                                                   0.0180666
annualized_returns                                                      0.0559331
benchmark_annualized_returns                                            0.0454542
benchmark_daily_returns                                               8.87784e-05
benchmark_total_returns                                                  0.525913
beta                                                                     0.518371
cash                                                                      4971.44
daily_returns                                                          0.00250376
downside_risk                                                            0.246409
information_rate                                                        0.0380054
market_value                                                               162796
max_drawdown                                                            -0.602535
pnl                                                                           419
portfolio_value                                                            167767
positions                       {'000068.XSHE': Position({{'value_percent': 0....
sharpe                                                                    2.35011
sortino                                                                   2.62967
total_commission                                                          2585.89
total_returns                                                            0.677674
total_tax                                                                 1172.01
tracking_error                                                           0.269138
trades                                                                         []
volatility                                                               0.275721
Name: 2016-07-01 00:00:00, dtype: object
'''

架構圖

Architecture
Architecture

FAQ

在Windows運行報Error on import matplotlib.pyplot

請訪問 Error on import matplotlib.pyplot (on Anaconda3 for Windows 10 Home 64-bit PC) 解決。

Python SDK 簡介

Python策略Hello World

以下的策略是最簡單的一個買入并持有平安銀行(buy and hold)的展示,非常簡單:

# 可以自己import我們平臺支持的第三方python模塊,比如pandas、numpy等。

# 在這個方法中編寫任何的初始化邏輯。context對象將會在你的算法策略的任何方法之間做傳遞。
def init(context):
    context.s1 = "000001.XSHE"
    # order是否被發送出去
    context.fired = False

# 你選擇的證券的數據更新將會觸發此段邏輯,例如日或分鐘歷史數據切片或者是實時數據切片更新
def handle_bar(context, bar_dict):
    # 開始編寫你的主要的算法邏輯

    # bar_dict[order_book_id] 可以拿到某個證券的bar信息
    # context.portfolio 可以拿到現在的投資組合狀態信息

    # 使用order_shares(id_or_ins, amount)方法進行落單

    # TODO: 開始編寫你的算法吧!
    if not context.fired:
        # order_percent并且傳入1代表買入該股票并且使其占有投資組合的100%
        order_percent(context.s1, 1)
        context.fired = True

需要實現的方法

你的算法策略目前必須實現至少兩個方法:inithandle_bar,而before_trading是可選擇實現的方法。

init

init(context)

初始化方法 - 在回測和實時模擬交易只會在啟動的時候觸發一次。你的算法會使用這個方法來設置你需要的各種初始化配置。
context 對象將會在你的算法的所有其他的方法之間進行傳遞以方便你可以拿取到。

參數 類型 注釋
context python簡單對象 將會在整個算法中當做一個全局變量來使用。屬性通過點標記(".")來取到。

返回
None

范例:

def init(context):
    # cash_limit的屬性是根據用戶需求自己定義的,你可以定義無限多種自己隨后需要的屬性,ricequant的系統默認只是會占用context.portfolio的關鍵字來調用策略的投資組合信息
    context.cash_limit = 5000

handle_bar

handle_bar(context, bar_dict)

切片數據的更新會自動觸發調用這個方法,如果是日回測則是每日的切片數據(OHLC)會觸發調用,分鐘回測則會是每分鐘的切片數據會調用,那么在實時模擬交易中則是實時每分鐘會調用一次。對于切片數據對象你可以看關于Bar對象的更詳細的信息。

參數 類型 注釋
context 和init方法中的context對象一樣 存儲所有策略的自己定義的變量狀態或是初始設置。
bar_dict bar dictionary - 存儲了關注的證券的bar的一個dict,order_book_id作為key 所有已‘關注’的股票的切片數據信息都會更新在這個dict里面。

返回
None

范例

def handle_bar(context, bar_dict):
    # put all your algorithm main logic here.
    # ...
    order_shares('000001.XSHE', 500)
    # ...

before_trading

非強制,可選擇實現的函數。每天在市場開始前會被調用。不可以在這個函數中發送訂單(即不可以調用order_xxxx函數)。

before_trading(context, bar_dict)
參數 類型 注釋
context 和init方法中的context對象一樣 存儲所有策略的自己定義的變量狀態或是初始設置,也保存了portfolio的信息。

返回
None

范例

def before_trading(context, bar_dict):
    context.stock_list = ["000001.XSHE", "000099.XSHE"]

    # 手動更新股票池
    update_universe(context.stock_list)

Order方法

你可以在策略中使用下面的幾種豐富的落單方法,他們不同的用法可以讓你落單的操作十分便捷。我們在交易系統內部提供好了倉位計算,因此你可以非常便利使用一些基于倉位管理上的落單方法,比如order_percent 可以讓你基于目前的倉位價值進行落單。

order_shares

落指定股數的買/賣單,最常見的落單方式之一。如有需要落單類型當做一個參量傳入,如果忽略掉落單類型,那么默認是市價單(market order)。

order_shares(id_or_ins, amount, style=MarketOrder())
參數 類型 注釋
id_or_ins str或instrument對象-required order_book_id或symbol或instrument對象
amount float-required 需要落單的股數。正數代表買入,負數代表賣出。將會根據一手xx股來向下調整到一手的倍數,比如中國A股就是調整成100股的倍數。
style OrderType-optional 訂單類型,默認是市價單。目前支持的訂單類型有:<ul><li>style=MarketOrder()</li><li>style=LimitOrder(<span></span>limit_price)</li></ul>

返回
int,唯一的order id

范例

  • 購買Buy 2000 股的平安銀行股票,并以市價單發送
order_shares('000001.XSHE', 2000)
  • 賣出2000股的平安銀行股票,并以市價單發送:
order_shares('000001.XSHE', -2000)
  • 購買1000股的平安銀行股票,并以限價單發送,價格為¥10:
order_shares('000001.XSHG', 1000, style=LimitOrder(10))

order_lots

指定手數發送買/賣單。如有需要落單類型當做一個參量傳入,如果忽略掉落單類型,那么默認是市價單(market order)。

order_lots(id_or_ins, amount, style=OrderType)
參數 類型 注釋
id_or_ins str或instrument對象-required order_book_id或symbol或instrument對象
amount float-required 多少手的數目。正數表示買入,負數表示賣出
style OrderType-optional 訂單類型,默認是市價單。目前支持的訂單類型有:<ul><li>style=MarketOrder</li><li>style=LimitOrder(<span></span>limit_price)</li></ul>

返回
int,唯一的order id

范例

  • 買入20手的平安銀行股票,并且發送市價單:
order_lots('000001.XSHE', 20)
  • 買入10手平安銀行股票,并且發送限價單,價格為¥10:
order_lots('000001.XSHE', 10, style=LimitOrder(10))

order_value

使用想要花費的金錢買入/賣出股票,而不是買入/賣出想要的股數,正數代表買入,負數代表賣出。股票的股數總是會被調整成對應的100的倍數(在A中國A股市場1手是100股)。當您提交一個賣單時,該方法代表的意義是您希望通過賣出該股票套現的金額。如果金額超出了您所持有股票的價值,那么您將賣出所有股票。

order_value(id_or_ins, cash_amount, style=OrderType)
參數 類型 注釋
id_or_ins str或instrument對象-required order_book_id或symbol或instrument對象
cash_amount float-required 需要花費現金購買/賣出證券的數目。正數代表買入,負數代表賣出。
style OrderType-optional 訂單類型,默認是市價單。目前支持的訂單類型有:<ul><li>style=MarketOrder()</li><li>style=LimitOrder(<span></span>limit_price)</li></ul>

返回
int,唯一的order id

范例

  • 買入價值¥10000的平安銀行股票,并以市價單發送。如果現在平安銀行股票的價格是¥7.5,那么下面的代碼會買入1300股的平安銀行,因為少于100股的數目將會被自動刪除掉。
order_value('000001.XSHE', 10000)
  • 賣出價值¥10000的現在持有的平安銀行:
order_value('000001.XSHE', -10000)

order_percent

發送一個等于目前投資組合價值(市場價值和目前現金的總和)一定百分比的買/賣單,正數代表買,負數代表賣。股票的股數總是會被調整成對應的一手的股票數的倍數(1手是100股)。百分比是一個小數,并且小于或等于1(<=100%),0.5表示的是50%

order_percent(id_or_ins, percent, style=OrderType)
參數 類型 注釋
id_or_ins str或instrument對象 -required order_book_id或symbol或instrument object.
percent float-required 占有現有的投資組合價值的百分比。正數表示買入,負數表示賣出。
style OrderType-optional 訂單類型,默認是市價單。目前支持的訂單類型有:<ul><li>style=MarketOrder()</li><li>style=LimitOrder(<span></span>limit_price)</li></ul>

返回
int,唯一的order id

范例

  • 買入等于現有投資組合50%價值的平安銀行股票。如果現在平安銀行的股價是¥10/股并且現在的投資組合總價值是¥2000,那么將會買入200股的平安銀行股票。(不包含交易成本和滑點的損失)
order_percent('000001.XSHG', 0.5)

order_target_value

買入/賣出并且自動調整該證券的倉位到一個目標價值。如果還沒有任何該證券的倉位,那么會買入全部目標價值的證券。如果已經有了該證券的倉位,則會買入/賣出調整該證券的現在倉位和目標倉位的價值差值的數目的證券。

order_target_value(id_or_ins, cash_amount, style=OrderType)
參數 類型 注釋
id_or_ins str或instrument對象-required order_book_id或symbol或instrument對象.
cash_amount float-required 最終的該證券的倉位目標價值
style OrderType-optional 訂單類型,默認是市價單。目前支持的訂單類型有:<ul><li>style=MarketOrder()</li><li>style=LimitOrder(<span></span>limit_price)</li></ul>

返回
int,唯一的order id

范例

  • 如果現在的投資組合中持有價值¥3000的平安銀行股票的倉位并且設置其目標價值為¥10000,以下代碼范例會發送價值¥7000的平安銀行的買單到市場。(向下調整到最接近每手股數即100的倍數的股數)
order_target_value('000001.XSHE', 10000)

order_target_percent

買入/賣出證券以自動調整該證券的倉位到占有一個指定的投資組合的目標百分比。

  • 如果投資組合中沒有任何該證券的倉位,那么會買入等于現在投資組合總價值的目標百分比的數目的證券。
  • 如果投資組合中已經擁有該證券的倉位,那么會買入/賣出目標百分比和現有百分比的差額數目的證券,最終調整該證券的倉位占據投資組合的比例至目標百分比。

其實我們需要計算一個position_to_adjust (即應該調整的倉位)

position_to_adjust = target_position - current_position

投資組合價值等于所有已有倉位的價值和剩余現金的總和。買/賣單會被下舍入一手股數(A股是100的倍數)的倍數。目標百分比應該是一個小數,并且最大值應該<=1,比如0.5表示50%。

如果position_to_adjust 計算之后是正的,那么會買入該證券,否則會賣出該證券。

order_target_percent(id_or_ins, percent, style=OrderType)
參數 類型 注釋
id_or_ins str或instrument對象-required order_book_id或symbol或instrument對象。
percent float-required 倉位最終所占投資組合總價值的目標百分比。
style OrderType-optional 訂單類型,默認是市價單。目前支持的訂單類型有:<ul><li>style=MarketOrder()</li><li>style=LimitOrder(<span></span>limit_price)</li></ul>

返回
int,唯一的order id

范例

  • 如果投資組合中已經有了平安銀行股票的倉位,并且占據目前投資組合的10%的價值,那么以下代碼會買入平安銀行股票最終使其占據投資組合價值的15%:
order_target_percent('平安銀行', 0.15)

cancel_order

取消由order_id代表的限價單。

cancel_order(order_id)

get_order

通過唯一的order_id拿到對應的訂單信息,不過這個訂單信息會在handle_bar結尾處丟棄掉。

get_order(order_id)
參數 類型 注釋
order_id int-required 訂單的唯一標示符

返回
order對象,如:

<Order: filled_shares=100.0 quantity=100.0 instrument=<Instrument: order_book_id='000001.XSHE' symbol='平安銀行' abbrev_symbol='PAYH' round_lot=100.0 sector_code='Financials' sector_name='金融'>>

get_open_orders

獲取一個由order_id到order對象映射的dict,凡在此dict中的order都未被完全成交或取消。


更改context中的預設值


更改默認基準

可以在init函數中使用:

def init(context):
    context.benchmark = "000001.XSHE"

上面的代碼片段把你的策略的對比參考基準從默認的csi300修改成了平安銀行。


開啟允許賣空

默認賣空是不允許的,不過我們提供了API可以開啟賣空,不會讓您的賣空單被我們的系統拒掉,可以在init函數中使用:

def init(context):
    context.short_selling_allowed = True

如果您在測試一些諸如統計套利(pair trading)需要允許賣空機制的策略的時候可以開啟這一項,不過注意到在中國A股市場賣空股票是一件非常難的事情。


更改滑點

可以在init函數中使用:

def init(context):
    context.slippage = 0.5

注意 : 其中的數值應為x%中的x, 例子中的0.5=0.5%。

上面的代碼片段把你的策略的滑點更改為了0.5%。


更改交易費

可以在init函數中使用:

def init(context):
    context.commission = 0.02

注意 : 其中的數值應為x%中的x, 例子中的0.02=0.02%,即萬分之2.

上面的代碼片段把你的策略使用的交易費更改為了0.02%。


scheduler方法

如果需要在某個日期、某個時間點運行一個函數,可以在init函數中使用scheduler, 注意:scheduler必須在init函數中調用。

scheduler.run_daily(function)
scheduler.run_weekly(function, weekday=x,tradingday=t)
scheduler.run_monthly(function, tradingday=t)

定日期運行

每天

每天運行一次傳入的function

scheduler.run_daily(function)
參數 類型 注釋
function function 使傳入的function每日運行

返回
None

注意
1, schedule一定在其對應時間點的handle_bar之后執行。

范例

以下的范例代碼片段是一個非常簡單的例子,在每天交易后查詢現在portfolio中剩下的cash的情況

def log_cash(context, bar_dict):
    logger.info("Remaning cash: %r" % context.portfolio.cash)

def init(context):
    #...
    # 每天運行一次
    scheduler.run_daily(log_cash)

每周某天

每周在固定的某天運行一下傳入的function

scheduler.run_weekly(function, weekday=x, tradingday=t)
參數 類型 注釋
function function 使傳入的function每日交易開始前運行
weekday int - required 1:周一,2:周二, ..., 5: 周五
tradingday int - not required 范圍為[-5,1],[1,5] 例:1(-1):每周(倒數)第一個交易日,n(-n):每周(倒數)第n個交易日

返回
None

注意
1, tradingday中的負數表示倒數。

2, tradingday表示交易日。如某周只有四個交易日,則此周的tradingday=4tradingday=-1表示同一天

3, weekdaytradingday不能同時使用。
范例

以下的代碼片段非常簡單,在每周二固定運行打印一下現在的portfolio剩余的資金:

def log_cash(context, bar_dict):
    logger.info("Remaning cash: %r" % context.portfolio.cash)

def init(context):
    #...
    # 每周二打印一下剩余資金:
    scheduler.run_weekly(log_cash, weekday=2)

    # 每周第二個交易日打印剩余資金:
    #scheduler.run_weekly(log_cash, tradingday=2)

每月某交易日

在每月的某個交易日運行一次傳入的function:

scheduler.run_monthly(function,tradingday=t)
參數 類型 注釋
function function 使傳入的function每日交易開始前運行
tradingday int - required 范圍為[-23,1], [1,23] ,如: 1(-1):每月(倒數)第一個交易日,2(-2):每月(倒數)第二個交易日, ..., 28(-28):每月(倒數)第28個交易日

返回
None

注意
1, tradingday的負數表示倒數

2, tradingday表示交易日,如某月只有三個交易日,則此月的tradingday=3與tradingday=-1表示同一天

范例
以下的代碼片段非常簡單的展示了每個月第一個交易日的時候我們進行一次財務數據查詢,這樣子會非常有用在一些根據財務數據來自動調節倉位股票組合的算法來說:

def query_fundamental(context, bar_dict):
        # 查詢revenue前十名的公司的股票并且他們的pe_ratio在25和30之間。打fundamentals的時候會有auto-complete方便寫查詢代碼。
    fundamental_df = get_fundamentals(
        query(
            fundamentals.income_statement.revenue, fundamentals.eod_derivative_indicator.pe_ratio
        ).filter(
            fundamentals.eod_derivative_indicator.pe_ratio > 25
        ).filter(
            fundamentals.eod_derivative_indicator.pe_ratio < 30
        ).order_by(
            fundamentals.income_statement.revenue.desc()
        ).limit(
            10
        )
    )

    # 將查詢結果dataframe的fundamental_df存放在context里面以備后面只需:
    context.fundamental_df = fundamental_df

    # 實時打印日志看下查詢結果,會有我們精心處理的數據表格顯示:
    logger.info(context.fundamental_df)
    update_universe(context.fundamental_df.columns.values)

# 在這個方法中編寫任何的初始化邏輯。context對象將會在你的算法策略的任何方法之間做傳遞。
def init(context):
    # 每月的第一個交易日查詢以下財務數據,以確保可以拿到最新更新的財務數據信息用來調整倉位
    scheduler.run_monthly(query_fundamental, tradingday=1)

定時間運行

scheduler還可以用來做定時間運行,比如在每天開盤后的一小時后或一分鐘后定時運行,這里有很多種組合可以讓您達到各種自己想要達到的定時運行的目的。

注意:使用time_rule定時運行只會在分鐘級別回測和實時模擬交易中有定義的效果,在日回測中只會默認依然在該天運行,并不能在固定的時間運行。

使用的方法是和上面的scheduler.run_daily,scheduler.run_weeklyscheduler.run_monthly進行組合加入time_rule來一起使用:

如何使用scheduler來進行定日期運行已經在上面解釋的很清楚了,這里我們主要介紹如何使用time_rule來進行定時間運行:

參數 類型 注釋
time_rule market_open / market_close 定時具體幾點幾分運行某個函數。這個可以設置為market_open - 開市后多久運行或market_close - 閉市前多久運行。如果不設置time_rule默認的值是開市后一分鐘運行。

martet_open /market_close參數如下:

參數 類型 注釋
hour int - option [0,4] 具體在market_open/market_close后/前第多少小時執行, 股票的交易時間為[9:30 - 11:30],[13:01 - 15:00]共240分鐘,所以hour的范圍為 [0,4]
minute int - option [0,240] 具體在market_open/market_close的后/前第多少分鐘執行,同上,股票每天交易時間240分鐘,所以minute的范圍為 [0,240],中午休市的時間區間會被忽略。

返回
None

每天的開市后某個時間點運行:

scheduler.run_daily(function, time_rule=market_open(hour=x, minute=x))

每周的閉市前某個時間點運行:

scheduler.run_weekly(function, weekday=w ,tradingday=t, time_rule=market_close(hour=x, minute=x))

每月的第t個交易日開市后某個時間點運行:

scheduler.run_monthly(function,traingday=t ,time_rule=market_open(hour=x, minute=x))

注意
1, 在分鐘回測中如未指定time_rule,則默認在開盤后一分鐘運行,即09:31分。
2, 如果兩個schedule,分別使用market_openmarket_close規則,但規則觸發時間在同一時刻,則market_openhandle一定在market_closehandle前執行。
3, 目前暫不支持開盤交易(即 09:30分交易) ,所以time_rule(minute=0)time_rule(hour=0) 將不會觸發任何事件。
4, market_open(minute=120)將在11:30執行, market_open(minute=121)在13:01執行,中午休市的區間會被忽略。
范例

  • 每天開盤后一小時:
scheduler.run_daily(function, time_rule=market_open(hour=1))
  • 每周周一開盤后一分鐘:
scheduler.run_weekly(function, weekday=1, time_rule=market_open(minute=1))
  • 每月第一個交易日收盤前一小時:
scheduler.run_monthly(function, tradingday=1,time_rule=market_close(hour=1))

其他方法

update_universe

update_universe(id_or_symbols)

這個方法傳入一個或一個列表的id_or_symbol(s)作為參數,用以更新現在關注的證券的集合(e.g
.:股票池)。PS:會在下一個bar事件觸發時候產生(新的關注的股票池更新)效果。并且update_universe會是覆蓋(overwrite)的操作而不是在已有的股票池的基礎上進行增量添加。比如已有的股票池為['000001 .XSHE', '000024.XSHE']然后調用了update_universe(['000030.XSHE'])之后,股票池就會變成000030 .XSHE一個股票了,隨后的數據更新也只會跟蹤000030.XSHE這一個股票了。

參數 類型 注釋
id_or_symbols str或iterable of strings 單個或一個id_or_symbol(s)列表.

范例

下面的代碼是將股票池變更為只有2個股票000001.XSHE000024.XSHE:

update_universe(['000001.XSHE', '000024.XSHE'])

instruments

instruments(id_or_symbols)

轉換單個string或一個string列表的order_book_id到instrument對象

參數 類型 注釋
id_or_symbols str或iterable of strings 單個或一個列表的order_book_id,中國市場的A股的order_book_ids是類似‘000001.XSHE’的寫法

返回

單個或一個列表的<a href="/api/python/chn#instrument-object" target="_blank">instrument對象</a> - 用id_or_symbol請求的。

范例

  • 只得到單個instrument的對象:
[In]instruments('000001.XSHE')
[Out]
<Instrument: industry_name='貨幣金融服務', listed_date=datetime.datetime(1991, 4, 3, 0, 0), round_lot=100.0, listing=False, abbrev_symbol='PAYH', symbol='平安銀行', industry_code='J66', type='CS', sector_code='Financials', sector_name='金融', order_book_id='000001.XSHE'>
  • 得到一個列表的instrument對象 - 中國股票:
[In]instruments(['平安銀行', '000024.XSHE'])
[Out]
[<Instrument: industry_name='貨幣金融服務', listed_date=datetime.datetime(1991, 4, 3, 0, 0), round_lot=100.0, listing=False, abbrev_symbol='PAYH', symbol='平安銀行', industry_code='J66', type='CS', sector_code='Financials', sector_name='金融', order_book_id='000001.XSHE'>,
<Instrument: industry_name='房地產業', listed_date=datetime.datetime(1993, 6, 7, 0, 0), round_lot=100.0, listing=False, abbrev_symbol='ZSDC', symbol='招商地產', industry_code='K70', type='CS', sector_code='Financials', sector_name='金融', order_book_id='000024.XSHE'>]

history

history(bar_count, frequency, field)

history函數返回所有已關注證券的歷史行情,同時支持日以及分鐘歷史數據。以pandas的DataFrame對象裝載為時間序列。

注意:在我們最新加入的可以動態處理調整證券池的功能以后,您并不只能使用history函數拿到已經加入證券池的歷史數據,您可以拿到所有想要拿的任意的證券的歷史數據了。

參數 類型 注釋
bar_count int-required 表示回溯的bar的數量
frequency str-required 表示回溯時以什么樣的頻率進行。例如"1d"或"1m"分別表示每日和每分鐘
field str-required 制定返回的DataFrame中以哪個指標作為數據值,可取“open”,“close”,“high”,“low”,“volume”,“last”, "total_turnover" - 總成交額

返回

DataFrame

范例:

  1. 拿取四天的歷史數據:
print (history(4, '1d', 'close')['000001.XSHE'])

當前日期:2013-01-05

日期 收盤價格
2013-01-02 12.0
2013-01-03 11.0
2013-01-04 13.0
2013-01-05 11.0
  1. 拿取四分鐘的歷史數據:
print(history(4, '1m', 'close')['000001.XSHE'])

當前時間:2014-01-06 09:34:00

日期 收盤價格
2014-01-06 09:31 8.2569
2014-01-06 09:32 8.2292
2014-01-06 09:33 8.2014
2014-01-06 09:34 8.2083

plot

plot(series_name, value)

plot函數可以將時間序列的數據傳給頁面進行繪圖,結果是以時間為橫軸,value為縱軸的曲線。

參數 類型 注釋
'series_name' str - required 繪制曲線的名稱
'value' float - required 當前日期的曲線的點的值

范例:

# 你選擇的證券的數據更新將會觸發此段邏輯,例如日或分鐘歷史數據切片或者是實時數據切片更新
def handle_bar(context, bar_dict):
    # TODO: 開始編寫你的算法吧!

    plot('close', bar_dict['000001.XSHE'].close)
    plot('high', bar_dict['000001.XSHE'].high)
    plot('low', bar_dict['000001.XSHE'].low)
    plot('open', bar_dict['000001.XSHE'].open)

拿到當前時間

context.now

使用以上的方法就可以在handle_bar中拿到當前的bar的時間,比如day bar的話就是那天的時間,minute bar的話就是這一分鐘的時間點。


Bar對象

Ricequant的后端算法交易系統會處理你的算法中所有關注的證券,我們支持的包括股票、ETF、LOF、分級基金和期貨。
它會發送bar事件并且將來還可以發送其他的事件給你的算法策略(比如:tick數據)。bar_dict是所有的關注的證券的bar數據的一個總集合,你可以在handle_bar中拿取到bar對象,其中包含了該證券的所有的市場數據信息。

例如,如果你想拿到平安銀行股票'000001.XSHE'的切片數據信息,那么可以使用這段代碼bar_dict['000001.XSHE']。下面會介紹我們已經支持的bar對象的屬性:

同時對bar對象我們也支持如下的轉換方法:

mavg(intervals, frequency='day')

可以用來計算某個證券的某段時間的移動平均價格,默認單位是‘天’

參數 類型 注釋
間隔 int 一段時間間隔,比如:3
頻率 str 間隔的頻率,默認是“天”
vwap(intervals, frequency='day')

可以用來計算某個證券的某段時間的加權平均價格,默認單位是“天”

參數 類型 注釋
間隔 int 一段時間間隔,比如:3
頻率 str 間隔的頻率,默認是“天”

Order對象

在order對象中的屬性:

參數 類型 注釋
instrument instrument對象 訂單對應的證券的instrument對象
filled_shares float 該訂單已經成交的股數
quantity float 該訂單的所有的股數

Portfolio對象

portfolio對象包含算法策略的所有的投資組合的信息。在日級別回測中,這表示的是每日收盤以后的投資組合信息。可以使用context.portfolio去拿取portfolio對象的信息。

并且有以下的屬性:

參數 類型 注釋
starting_cash float 回測或實盤交易給算法策略設置的初始資金
cash float 現在投資組合中剩余的現金
total_returns float 算法投資組合至今的累積百分比收益率。計算方法是現在的投資組合價值/投資組合的初始資金。投資組合價值包含剩余現金和其市場價值。
daily_returns float 當前最新一天的每日收益。
market_value float 投資組合當前的市場價值(未實現/平倉的價值)
portfolio_value float 當前投資組合的總共價值,包含市場價值和剩余現金。
pnl float 當前投資組合的¥盈虧
start_date DateTime 策略投資組合的回測/實時模擬交易的開始日期
annualized_returns float 投資組合的年化收益率
positions Dictionary 一個包含所有倉位的字典,以id_or_symbol作為鍵,position對象作為值,關于position的更多的信息可以在下面的部分找到。
dividend_receivable float 投資組合在分紅現金收到賬面之前的應收分紅部分。具體細節在分紅部分

Position對象

position對象代表一個證券的倉位信息。可以通過positions字典拿到,例如:如果你的投資組合有平安銀行股票(000001.XSHE)的倉位,你可以通過以下代碼拿到它的倉位:

context.portfolio.positions['000001.XSHE']

并且position對象有以下的屬性:

參數 類型 注釋
quantity int 未平倉部分的總股數。
bought_quantity int 該證券的總買入股數,例如:如果你的投資組合并沒有任何平安銀行的成交,那么平安銀行這個股票的倉位就是0.
sold_quantity int 該證券的總賣出股數,例如:如果你的投資組合曾經買入過平安銀行股票200股并且賣出過100股,那么這個屬性會返回100.
bought_value float 該證券的總買入的價值,等于每一個該證券的買入成交的價格*買入股數的總和。
sold_value float 該證券的總賣出價值,等于每一個該證券的賣出成交的價格*賣出股數的總和。
total_orders int 該倉位的總訂單的次數。
total_trades int 該倉位的總成交的次數。
sellable int 該倉位可賣出股數。T+1的市場中sellable = 所有持倉-今日買入的倉位。
average_cost float 獲得該持倉的買入均價,計算方法為每次買入的數量做加權平均。
market_value float 獲得該持倉的實時市場價值。
value_percent float 獲得該持倉的實時市場價值在總投資組合價值中所占比例,取值范圍[0, 1]。

Instrument對象

Instrument代表所有的金融證券,例如:可以是股票,ETF,指數和期貨合同。

股票,ETF,指數Instrument對象

股票,ETF,指數Instrument對象有如下的屬性:

參數 類型 注釋
order_book_id str 證券的獨特的標識符。
symbol str 證券的易讀的名字。
abbrev_symbol str 證券的名稱縮寫,比如:在中國A股就是股票的拼音縮寫,‘PAYH’就是平安銀行股票的證券名縮寫。
round_lot int 一手是多少股,中國A股一手是100股。
sector_code str 板塊縮寫代碼,全球通用標準定義。
sector_name str 以當地語言為標準的板塊代碼名。
industry_code str 國民經濟行業分類代碼。
industry_name str 國民經濟行業分類名稱。
listing bool 該證券是否還在交易所交易。
listed_date DateTime 該證券的上市日期。
type str 需要使用種類簡稱,下面的type列表會解釋我們目前支持的證券類型:'CS', 'INDX', 'LOF', 'ETF', 'FenjiMu', 'FenjiA', 'FenjiB', 'Future'
board_type str 'MainBoard' - 主板,'GEM' - 創業板

開發

pyvenv venv
source venv/bin/activate
pip install -e .

運行單元測試

py.test
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,748評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,165評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,595評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,633評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,435評論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,943評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,035評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,175評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,713評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,599評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,788評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,303評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,034評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,412評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,664評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,408評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,747評論 2 370

推薦閱讀更多精彩內容