跳转至


课程  因子投资  机器学习  story  量化传奇  Python  Poetry  ppw  tools  programming  Numpy  Pandas  pandas  算法  hdbscan  聚类  选股  Algo  minimum  numpy  algo  FFT  模式识别  配对交易  GBDT  LightGBM  XGBoost  statistics  CDF  KS-Test  monte-carlo  VaR  回测  过拟合  algorithms  machine learning  strategy  python  sklearn  pdf  概率  数学  面试题  Info  interview  career  xgboost  PCA  wavelet  Figures  Behavioral Economics  人物  职场  Quantopian  figure  Banz  rsi  zigzag  穹顶压力  因子  pe  ORB  策略  Xgboost  factor  alpha101  alpha  技术指标  wave  quant  algorithm  pearson  spearman  tushare  因子分析  Alphalens  涨停板  herd-behaviour  因子策略  momentum  因子评估  review  trade  history  indicators  zscore  波动率  强化学习  顶背离  freshman  resources  others  AI  DeepSeek  network  weekly  LLT  backtest  backtrader  研报  papers  UBL  quantlib  jupyter-notebook  scikit-learn  pypinyin  qmt  xtquant  blog  static-site  duckdb  工具  colors  free resources  barra  world quant  Alpha  openbb  数据  risk-management  llm  prompt  CANSLIM  Augment  arsenal  copilot  vscode  code  量化数据存储  hdf5  h5py  cursor  augment  trae  Jupyter  jupysql  pyarrow  parquet  数据源  quantstats  实盘  clickhouse  notebook  redis  remote-agent  AI-tools  Moonshot  回测,研报,tushare 

东财量化接口安装指南


【目录】

1. 安装与配置

1.1. 安装

  1. 在windows机器上安装https://emt.eastmoneysec.com/down,下载并安装第二个软件:

  2. 在同一台机器上安装conda,推荐安装miniconda,并创建虚拟运行环境(python版本3.8):

    1
    conda create -n gmclient python=3.8
    

  3. 安装gmadaptor:
    1
    pip install gmadaptor-1.1.3-py3-none-any.whl
    

1.2. 申请权限

请加入东方财富量化仿真交流群:971584613 ,找管理员申请开通量化实盘权限。请先看群置顶文件。 开通的主要门槛是要求100万初始资金。开通后可以撤资。

1.3. 模拟和测试

在等待实盘权限开通的过程中,可以通过 https://emt.18.cn/apply/test-apply-client 开通模拟账号,先把程序和配置调通。

申请后,记录普通资金账号和密码,如下图:

在登录界面中,选择仿真交易:

登录后,界面显示如下:

1.3.1. 配置账号

以下步骤对实盘和模拟盘均有效。

1.3.1.1. gmadaptor的配置文件

需要将量化软件中的实盘账号配置到gmadaptor的配置文件中。在用户目录下,创建gmadaptor/config目录,放置以下文件:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# defaults.yaml
log_level: INFO

server_info:
    port: 9000
    # client 使用这一token来访问 gmadaptor 提供的服务
    access_token : "84ae0899-7a8d-44ff-9983-4fa7cbbc424b"

gm_info:
    fake: false
    # 文件单输出目录
    gm_output: "~/gmadaptor/FileOrders/out"
    trade_fees:
        commission: 2.5
        stamp_duty: 10.0
        transfer_fee: 0.1
        minimum_cost: 5.0
    accounts:
        # 账号名
        - name: fileorder_s01
          acct_id: 1a66e81c-ae5d-11ec-aef5-00163e0a4100
          # 文件单输入目录。东财量化终端将从这里读取文件单
          acct_input: "~/gmadaptor/FileOrders/inputs/fileorder_s01"
上述配置中,access_token 可任意指定,任何要访问此服务的客户端,必须持有此 token。

gm_output/acct_input 文件设置后,如果未创建,gmadaptor 将在启动时自动创建,请确保 gmadaptor 有权限读写这些文件夹。

accounts > name 中的值来自于在 EMC 终端中,您创建文件单输入时,指定的名称,见下图中的序号2:

accounts > acct_id 来自于下面序号3的位置,点击ID即可复制:

1.3.1.2. 配置EMC

在 量化 > 文件单 > 文件单输出 中,对下图中的 4,5,6,7 进行配置。其中4选择我们在上面配置文件中gm_output中设置的路径;5选择csv作为输出格式;6选择自动启动;7将所有项目全选中。

在 量化 > 文件单 > 文件单输入 中,对下图中的 3和4进行配置。其中3选择我们在上面配置文件中设置的 acct_input 路径,4选择自动启动。

1.3.2. 模拟运行

在前面生成的gmclient虚拟环境中,执行以下命令,以启动gmadaptor服务器:

1
python -m gmadaptor.server
如果出现如下界面,表明服务器启动成功:

此时我们另开一个conda窗口,同样使用gmclient的虚拟环境,通过以下命令进行测试:

1
python -m gmtest %account %token %server %port

这里的account即 gmadaptor配置文件中的 gm_info > accounts > account_id, token 即server_info > access_token

这里的 server 即gmadaptor 所在的机器IP, port为端口。如果不提供,默认地,这两项分别为localhost和9000。

如果配置正常,这将打印出初始账号资金,当前持仓,和一笔买、卖的信息。

1.4. 运行和维护

另外启动一个计划任务,在每天早上8:45左右启动EMC。

1.4.1. 启动

使用下面的脚本来启动:

1
2
3
4
5
@echo off
call C:\ProgramData\Anaconda3\Scripts\activate.bat C:\ProgramData\anaconda3
call conda activate gmclient
python -m gmadaptor.server
pause

1.4.2. 每日维护

EMC量化终端有时候不稳定。我们可以通过定时重启来提高起稳定性。通过以下代码,在盘后退出EMC:

1
2
3
4
5
6
7
8
9
REM kill process
TASKKILL /F /IM EMCTrade.exe

REM sleep 5 seconds
TIMEOUT  /T 5

REM remove all file orders after process killed

DEL /Q C:\zillionare\FileOrders\real_input\*.csv

Warning

如果在输入输出目录中还有未归档的文件,则量化交易将无法自动启动。上述代码中最后一行的作用就是清理未归档文件。 这也要求使用者自行对委托进行核验,确保这些文件可以被自动删除。

2. 客户端与服务器交互

2.1. 客户端请求

客户端通过 http request来请求gmadaptor。以下示例均以同步请求实现,但您也可以根据需要,改为异步请求。服务器对客户端的鉴权是通过headers来实现的,具体请看示例(任意一示例均可)。客户端向服务器发送数据,都使用的是post方法,gmadaptor所有的方法都只响应post请求。如果请求成功完成,则返回代码是200。

在所有的操作中,股票代码都必须以简码+交易所后缀方式出现,其中上交所为.XSHG,深交所为.XSHE。在仿真测试时,对股票进行操作时,都有特定的响应(比如对某支股票,进行买入时,无论给的参数是多少,返回都会是部分成交;对另一支股票,则永远返回限制买入等等),具体响应文档请在东财量化Q群中,找管理员要文档。

在一些会改变状态的请求中(比如买入操作),往往会需要cid参数和timeout参数,其作用是,调用会在指定的timeout期间等待EMC处理请求,并返回结果;但EMC也可能无法在指定的timeout期间返回结果,比如委买单报价过低,一直不能成交,此时将无法产生回报结果。在这种情况下,调用会在timeout之后返回。之后的委买结果查询,就需要依赖cid参数。注意cid是必选参数,timeout是可选参数。

cid参数(即client entrust id)由客户端自行产生,建议使用以下代码:

1
2
3
import uuid

cid = str(uuid.uuid4())
cid产生之后,请在客户端保存,直到事务结束,不再需要为止。

为简练起见,以下示例中,可能删除了这些代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
import httpx
headers = {
    "Authorization": "84ae0899-7a8d-44ff-9983-4fa7cbbc424b",
    "Account-ID": "780dc4fda3d0af8a2d3ab0279bfa48c9"
}

_url_prefix = "http://192.168.100.100:9000/"

buy_entrust_no = None
sell_entrust_no = None

2.2. 返回结果

返回错误可能发生在三个层面。一是http层(包括 bad request 或者 Internal server error); 二是 gmadaptor层,三是 emc可能返回错误。

第一层的错误,我们通过 http status code来检查。比如,如果我们使用的客户端是httpx,则可以检查 response.status_code是否为200。

gmadaptor始终通过json来返回响应,响应包括三个字段,即:

1
2
3
status: int,如果为零,则表明在此层没有发生错误,即gmadaptor已经将请求正确上报
msg: str, human readable message
data: dict 如果一切顺利,则返回数据在此项中
第三层的错误由 emc trader给出。即使gmadaptor正确上报的请求,也可能emc trader无法执行,此时它也会通过statusreason来给出错误信息。

下面的示例给出了一个response.json()的输出:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
{
    "status": 0,
    "msg": "OK",
    "data": {
        "code": "000001.XSHE",
        "price": 0.0,
        "volume": 100,
        "order_side": 1,
        "bid_type": 2,
        "time": "2023-04-04 15:27:38.921555",
        "entrust_no": "0d23bb4e-d81e-4ef2-ab21-c58e0fe6814f",
        "status": -1,
        "average_price": 0.0,
        "filled": 0,
        "filled_amount": 0,
        "eid": "",
        "trade_fees": 0,
        "reason": "[Counter] [EMC_PC]不支持该下单类型",
        "recv_at": "2023-04-04 15:27:38.924565"
    }
}
因此,即使在gmadator层面给出的状态是成功,也并不意味着该笔委托成功。另一个例子是,以过低的价格委买,只要参数合法且被EMC接收,gmadaptor都会返回成功,但该委托是否真正成交,还得通过entrust_no来查询。

2.3. 资产表

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# 请求资金信息
import httpx
headers = {
    "Authorization": "84ae0899-7a8d-44ff-9983-4fa7cbbc424b",
    "Account-ID": "780dc4fda3d0af8a2d3ab0279bfa48c9"
}

_url_prefix = "http://192.168.100.100:9000/"

def get_balance():
    r = httpx.post(_url_prefix + "balance", headers=headers)
    resp = r.json()
    if r.status_code == 200 and resp['status'] == 0:
        print("\n------ 账户资金信息 ------")
        print(resp["data"])

2.4. 持仓表

1
2
3
4
5
6
7
def get_positions():
    r = httpx.post(_url_prefix + "positions", headers=headers)

    resp = r.json()
    if r.status_code == 200 and resp['status'] == 0:
        print("\n----- 持仓信息 ------")
        print(resp["data"])

2.5. 限价买入

1
2
3
4
5
6
7
8
9
    r = httpx.post(_url_prefix + "buy", headers=headers, json={
        "security": "000001.XSHE",
        "price": 13,
        "volume": 100,
        "cid": str(uuid.uuid4()),
        "timeout": 1
    })

    print(r.json())

2.6. 市价买入

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
def market_buy():
    global buy_entrust_no
    r = httpx.post(_url_prefix + "market_buy", headers=headers, json={
        "security": "000001.XSHE",
        "volume": 100,
        "cid": cid,
        "timeout": 1
    })

    resp = r.json()
    if r.status_code == 200 and resp["status"] == 0:
        print("\n ------ 委买成功 ------")
        print(resp["status"], resp["msg"], resp["data"])
        buy_entrust_no = resp["data"]["entrust_no"]
    else:
        print("委买失败:", r.status_code, resp)

2.7. 限价卖出

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
def sell():
    global sell_entrust_no

    r = httpx.post(_url_prefix + "sell", headers=headers, json={
        "security": "000001.XSHE",
        "price": 10,
        "volume": 100,
        "cid": cid,
        "timeout": 1
    })

    resp = r.json()
    if r.status_code == 200 and resp["status"] == 0:
        print("\n ------ 限价委卖成功 ------")
        data = resp["data"]
        print(data)
        sell_entrust_no = data["entrust_no"]
    else:
        print("卖出失败:", r.status_code, resp)

2.8. 市价卖出

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
def market_sell():
    r = httpx.post(_url_prefix + "market_sell", headers=headers, json = {
        "security": "000001.XSHE",
        "volume": 100,
        "cid": cid
    })

    resp = r.json()
    if r.status_code == 200 and resp["status"] == 0:
        print("\n ------ 市价委卖成功 ------")
        print(resp["data"])
    else:
        print(resp)

2.9. 取消委托

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
def cancel_entrust():
    global buy_entrust_no

    r = httpx.post(_url_prefix + "cancel_entrust", headers=headers, json = {
        "entrust_no": buy_entrust_no,
        "timeout": 1
    })

    resp = r.json()
    print(resp["status"], resp["msg"], resp["data"])

2.10. 查询当日委托

1
2
3
4
5
6
7
8
9
def today_entrusts():
    r = httpx.post(_url_prefix + "today_entrusts", headers=headers, json = {
        # 此处可以传入记录的委托号。传入空数组时,表明取当天所有委托。
        "entrust_no": [],
        "timeout": 1
    })

    resp = r.json()
    print(resp["status"], resp["msg"], resp["data"])

3. 故障排除与帮助

关于东财文件单,请参考:https://emquant.18.cn/file-help/?doc=file_order 东财量化Q群:971584613

即使实现了EMC的每日自动重启,也有可能偶发连接异常或者其它错误。此时可能需要手动执行: 1. 重新连接 2. 清除文件单,重新启动

撮合配置规则

在仿真交易测试中,EMTrader对每个品种,都指定了对应的响应。比如,对000572这个品种,买入一定会全部成交,对000010这个品种,则一定会拒绝。这是为了方便测试的需要。东财提供了名为《撮合配置规则》的文件,该文件可能随时更新,所以,需要在测试前,加他们技术人员QQ领取。

该文件2023年3月份部分内容如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
[全部成交]
000572  full
000725  full

[分笔成交] 
分成两笔:
000002  lot         2

[部分成交] 成交一半
000001  part
000004  part
...
[挂单]    只有响应,没有成交
018014  pending
020417  pending
...

[拒单]    
000010  reject
010609  reject

[拒绝撤单] 部分成交,不可撤单
000008  cancel_reject
000151  cancel_reject

联系方式

如果您在使用本模块中需要帮助,或者需要参加《大富翁量化编程实战课》学习,请添加 宽粉 的微信: