• QAACCOUNT 账户类
    • QA_Account() 是 quantaxis 的核心类
    • 其作用是一个可以使用规则兼容各种市场的账户类
    • 1.3.0以后, QA_Account 需要由组合来进行创建(推荐)
In [ ]:
    QA_User 
    User-->Portfolio-->Account/Strategy
    user ==> username / user_cookie
                            ||
                        portfolio  ==> portfolio_cookie
                                            ||
                                        accounts ==> account_cookie
    :::::::::::::::::::::::::::::::::::::::::::::::::
    ::        :: Portfolio 1 -- Account/Strategy 1 ::
    ::  USER  ::             -- Account/Strategy 2 ::
    ::        :: Portfolio 2 -- Account/Strategy 3 ::
    :::::::::::::::::::::::::::::::::::::::::::::::::
    :: 需要增加对于QA_USER的支持
    USER作为一个单位实体, 可以自由创建组合Portfolio (需要被记录),修改组合Portfolio
In [169]:
import QUANTAXIS as QA
  • 参考路径
    • QUANTAXIS/QUANTAXIS/QAARP/QAUser.py
    • QUANTAXIS/QUANTAXIS/QAARP/QAPortfolio.py
    • QUANTAXIS/QUANTAXIS/QAARP/QAAccount.py
    • QUANTAXIS/QUANTAXIS/QAARP/QAAccountPro.py
In [174]:
# 先创建一个用户
user = QA.QA_User(username ='quantaxis', password = 'quantaxis')
# 为该用户创建一个组合
portfolio=user.new_portfolio('x1')
# 为该组合创建一个账户,关键字段是 account_cookie
# 此账户也可以理解为策略,相关策略将于账户挂钩
account = portfolio.new_account(account_cookie='jasper')# 进行账户初始化
 prortfolio with user_cookie  USER_kypHwnuG  already exist!!
QAACCOUNT: THIS ACCOUNT DOESNOT HAVE ANY TRADE
QAACCOUNT: THIS ACCOUNT DOESNOT HAVE ANY TRADE
QAACCOUNT: THIS ACCOUNT DOESNOT HAVE ANY TRADE
QAACCOUNT: THIS ACCOUNT DOESNOT HAVE ANY TRADE
In [215]:
# 打印 user 的组合
user.portfolio_list
Out[215]:
['qatestportfolio', 'x1']
In [216]:
# 打印 account_cookie 列表
portfolio.account_list
Out[216]:
['jasper', 'stock']
In [221]:
# 移除一个账户
portfolio.drop_account('x1')
QAACCOUNT: THIS ACCOUNT DOESNOT HAVE ANY TRADE
QAACCOUNT: THIS ACCOUNT DOESNOT HAVE ANY TRADE
Out[221]:
True

股票普通账户

In [222]:
stock_account = portfolio.new_account(
      account_cookie ='stock'
    , allow_t0 = False
    , allow_margin = False
    , allow_sellopen = False
    , running_environment = QA.MARKET_TYPE.STOCK_CN
)
QAACCOUNT: THIS ACCOUNT DOESNOT HAVE ANY TRADE
QAACCOUNT: THIS ACCOUNT DOESNOT HAVE ANY TRADE
QAACCOUNT: THIS ACCOUNT DOESNOT HAVE ANY TRADE
QAACCOUNT: THIS ACCOUNT DOESNOT HAVE ANY TRADE

账户的初始资金/初始仓位

  • 默认账户是无仓位, 默认现金 1000000 RMB
In [223]:
stock_account.init_assets
Out[223]:
{'cash': 1000000, 'hold': {}}
In [224]:
stock_account.init_cash
Out[224]:
1000000
In [225]:
stock_account.init_hold
Out[225]:
Series([], Name: amount, dtype: float64)

移除账户 stock 再重建

In [228]:
# 移除一个账户
portfolio.drop_account('stock')
QAACCOUNT: THIS ACCOUNT DOESNOT HAVE ANY TRADE
QAACCOUNT: THIS ACCOUNT DOESNOT HAVE ANY TRADE
Out[228]:
True

在实例化的时候初始化仓位信息

  • 使用json/dict的格式初始化
  • init_hold={'000948': 100, '300872': 200}

在实例化的时候初始现金信息

  • init_cash = 50000
In [229]:
stock_account = portfolio.new_account(
      account_cookie ='stock'
    , init_cash = 50000
    , init_hold={'000948': 100, '300872': 200}
    , allow_t0=False
    , allow_margin=False
    , allow_sellopen=False
    , running_environment=QA.MARKET_TYPE.STOCK_CN
)
QAACCOUNT: THIS ACCOUNT DOESNOT HAVE ANY TRADE
QAACCOUNT: THIS ACCOUNT DOESNOT HAVE ANY TRADE
QAACCOUNT: THIS ACCOUNT DOESNOT HAVE ANY TRADE
QAACCOUNT: THIS ACCOUNT DOESNOT HAVE ANY TRADE
In [230]:
portfolio.init_hold_table
Out[230]:
amount
code account_cookie
000948 stock 100.0
300872 stock 200.0
In [231]:
stock_account.sell_available
Out[231]:
code
000948    100
300872    200
Name: amount, dtype: int64
In [232]:
stock_account.cash_available
Out[232]:
50000

在已经实例化的账户中修改现金/ 重置现金操作

In [233]:
stock_account.reset_assets(init_cash=666000)
In [234]:
stock_account.init_assets
Out[234]:
{'cash': 666000, 'hold': {'000948': 100, '300872': 200}}

买入/卖出操作

  • 有2种方式可以买入/卖出品种
    • send_order 接口 + Order类调用receive_deal 接口
      • 基于账户-发出订单- 订单成交回报的模式更新账户
    • receive_simpledeal 接口
      • 直接修改账户的模式, 由用户自行确认和保证成交

订单/更新账户的模式

生成订单

In [238]:
order = stock_account.send_order(
      code='000001'
    , amount=100
    , time='2019-01-19'
    , amount_model=QA.AMOUNT_MODEL.BY_AMOUNT
    , order_model=QA.ORDER_MODEL.CLOSE
    , price=10
    , towards=QA.ORDER_DIRECTION.BUY
)
In [240]:
future_account = portfolio.new_account(
      account_cookie ='future'
    , allow_t0=True
    , allow_margin=True
    , allow_sellopen=True
    , running_environment=QA.MARKET_TYPE.FUTURE_CN
)
QAACCOUNT: THIS ACCOUNT DOESNOT HAVE ANY TRADE
QAACCOUNT: THIS ACCOUNT DOESNOT HAVE ANY TRADE
QAACCOUNT: THIS ACCOUNT DOESNOT HAVE ANY TRADE
QAACCOUNT: THIS ACCOUNT DOESNOT HAVE ANY TRADE
In [241]:
future_order = future_account.send_order(
      code='RB1905'
    , amount=100
    , time='2019-01-19'
    , amount_model=QA.AMOUNT_MODEL.BY_AMOUNT
    , order_model=QA.ORDER_MODEL.CLOSE
    , price=3500
    , towards=QA.ORDER_DIRECTION.BUY_OPEN
)

订单类 QA_Order

In [236]:
order
Out[236]:
< QA_Order realorder_id Order_DyHo8ZGx datetime:2019-01-19 09:31:00 code:000001 amount:100 price:10 towards:1 btype:stock_cn order_id:Order_DyHo8ZGx account:stock status:queued >
In [242]:
future_order
Out[242]:
< QA_Order realorder_id Order_FUTpeHMd datetime:2019-01-19 09:31:00 code:RB1905 amount:100 price:3500 towards:2 btype:stock_cn order_id:Order_FUTpeHMd account:future status:queued >

订单交易(成交在Market/Broker中判断,此处只演示成交回报)

In [243]:
order.trade(trade_price=10.1,trade_amount=100,trade_id='example_trade1',trade_time='2019-01-19 15:00:00')
QAACCOUNT ==> receive deal  Time 2019-01-19 15:00:00/ Code:000001/ Price:10.1/ TOWARDS:1/ Amounts:100
Out[243]:
{'user_id': 'stock',
 'order_id': 'Order_UsfRZkBm',
 'trade_id': 'example_trade1',
 'exchange_id': None,
 'instrument_id': '000001',
 'exchange_trade_id': 'example_trade1',
 'direction': 'BUY',
 'offset': 'OPEN',
 'volume': 100,
 'price': 10.1,
 'trade_date_time': '2019-01-19 15:00:00',
 'commission': 5,
 'seqno': ''}
In [244]:
future_order.trade(trade_price=3600,trade_amount=100,trade_id='example_trade2',trade_time='2019-01-19 21:00:00')
QAACCOUNT ==> receive deal  Time 2019-01-19 21:00:00/ Code:RB1905/ Price:3600.0/ TOWARDS:2/ Amounts:100
Out[244]:
{'user_id': 'future',
 'order_id': 'Order_FUTpeHMd',
 'trade_id': 'example_trade2',
 'exchange_id': None,
 'instrument_id': 'RB1905',
 'exchange_trade_id': 'example_trade2',
 'direction': 'BUY',
 'offset': 'OPEN',
 'volume': 100,
 'price': 3600.0,
 'trade_date_time': '2019-01-19 21:00:00',
 'commission': 90.0,
 'seqno': ''}

账户成交表 QA_Account.history/QA_Account.history_table

In [245]:
stock_account.history_table
Out[245]:
datetime code price amount cash order_id realorder_id trade_id account_cookie commission tax message frozen direction total_frozen
0 2019-01-19 15:00:00 000001 10.1 100.0 664985.0 Order_UsfRZkBm Order_UsfRZkBm example_trade1 stock 5 0 None 0 1 0
In [247]:
future_account.history_table
Out[247]:
datetime code price amount cash order_id realorder_id trade_id account_cookie commission tax message frozen direction total_frozen
0 2019-01-19 21:00:00 RB1905 3600.0 100.0 675919.0 Order_FUTpeHMd Order_FUTpeHMd example_trade2 future 81.0 0 None 324000.0 2 324000.0

账户现金表/ 期货账户还会冻结资金(保证金)

In [248]:
stock_account.cash
Out[248]:
[666000, 664985.0]
In [249]:
future_account.cash
Out[249]:
[1000000, 675919.0]
In [250]:
future_account.frozen
Out[250]:
{'RB1905': {'2': {'money': 3240.0, 'amount': 100, 'avg_price': 3240.0},
  '-2': {'money': 0, 'amount': 0, 'avg_price': 0}}}

账户可用现金

In [251]:
stock_account.cash_available
Out[251]:
664985.0
In [252]:
future_account.cash_available
Out[252]:
675919.0

账户持仓

In [253]:
stock_account.hold
Out[253]:
code
000001    100.0
000948    100.0
300872    200.0
Name: amount, dtype: float64
In [254]:
future_account.hold
Out[254]:
code
RB1905    100.0
Name: amount, dtype: float64

账户可卖余额(股票T+1 因此可卖部分不增加/ 期货账户 t+0 因此可卖部分增加)

In [255]:
stock_account.sell_available
Out[255]:
code
000948    100
300872    200
Name: amount, dtype: int64
In [256]:
future_account.sell_available
Out[256]:
code
RB1905    100
Name: amount, dtype: int64

直接操作账户模式

In [257]:
stock_account.receive_simpledeal(
      code='000004'
    , order_id='model2'
    , realorder_id='model2_real'
    , trade_id='trade2'
    , trade_amount=1000
    , trade_price=16
    , trade_time='2019-01-21'
    , trade_towards=QA.ORDER_DIRECTION.BUY
    , message='model2'
)
Out[257]:
0
In [258]:
stock_account.history_table
Out[258]:
datetime code price amount cash order_id realorder_id trade_id account_cookie commission tax message frozen direction total_frozen
0 2019-01-19 15:00:00 000001 10.1 100.0 664985.0 Order_UsfRZkBm Order_UsfRZkBm example_trade1 stock 5 0 None 0 1 0
1 2019-01-21 000004 16.0 1000.0 648980.0 model2 model2_real trade2 stock 5 0 model2 0 1 0
In [259]:
stock_account.cash
Out[259]:
[666000, 664985.0, 648980.0]
In [260]:
stock_account.cash_available
Out[260]:
648980.0
In [261]:
stock_account.hold
Out[261]:
code
000001     100.0
000004    1000.0
000948     100.0
300872     200.0
Name: amount, dtype: float64
In [262]:
stock_account.sell_available
Out[262]:
code
000948    100
300872    200
Name: amount, dtype: int64

结算

  • 主要是股票账户的可卖股数的结算
  • 目前期货账户不采用逐日盯市的结算方式(及无结算价/无当日盈亏)
In [263]:
stock_account.settle()
In [264]:
stock_account.sell_available
Out[264]:
code
000001     100.0
000004    1000.0
000948     100.0
300872     200.0
Name: amount, dtype: float64
In [265]:
future_account.settle()

存储

In [266]:
stock_account.save()