text: # -*- coding: utf-8 -*-
  """
  Created on Mon Aug 21 14:24:31 2017
  
  Trade 模块需要配合TdxTradeServer使用...
  
  @author: RainX
  """
  import requests
  import urllib
  import json
  import base64
  from cryptography.hazmat.backends import default_backend
  from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
  
  try:
      from pytdx.log import log
  except ImportError:
      log = lambda x:None
  
  try:
      import pandas as pd
  except ImportError as e:
      pass
  
  
  class TdxTradeApiParams:
  
      """
      0 资金
      1 股份
      2 当日委托
      3 当日成交
      4 可撤单
      5 股东代码
      6 融资余额
      7 融券余额
      8 可融证券
      9
      10
      11
      12 可申购新股查询
      13 新股申购额度查询
      14 配号查询
      15 中签查询
      """
      QUERY_CATEGORY_CASH     = 0
      QUERY_CATEGORY_STOCKS   = 1
      QUERY_CATEGORY_ORDER_OF_TODAY       = 2
      QUERY_CATEGORY_DEAL_OF_TODAY        = 3
      QUERY_CATEGORY_CANCELABLE_ORDER     = 4
      QUERY_CATEGORY_SHAREHOLDERS_CODE    = 5
      QUERY_CATEGORY_BALANCE_OF_MARGIN_LOAN   = 6
      QUERY_CATEGORY_BALANCE_OF_STOCK_LOAN    = 7
      QUERY_CATEGORY_OPERABLE_MARGIN_SOTCK    = 8
  
      QUERY_CATEGORY_NEW_STOCKS       = 12
      QUERY_CATEGORY_NEW_STOCKS_QUOTA = 13
      QUERY_CATEGORY_NEW_STOCK_NUMBER = 14
      QUERY_CATEGORY_NEW_STOCK_HIT    = 15
  
  
  
  
  class TdxTradeApi(object):
      def __init__(self, endpoint="http://127.0.0.1:10092/api", encoding="utf-8", enc_key=None, enc_iv=None):
  
          self._endpoint = endpoint
          self._encoding = "utf-8"
          if enc_key == None or enc_iv == None:
              self._transport_enc = False
              self._transport_enc_key = None
              self._transport_enc_iv = None
              self._cipher = None
          else:
              self._transport_enc = True
              self._transport_enc_key = enc_key
              self._transport_enc_iv = enc_iv
              backend = default_backend()
              self._cipher = Cipher(algorithms.AES(enc_key), modes.CBC(enc_iv), backend=backend)
  
          self._session = requests.Session()
  
      def call(self, func, params=None):
  
          json_obj = {
              "func": func
          }
  
          if params is not None:
              json_obj["params"] = params
  
          if self._transport_enc:
              data_to_send = self.encrypt(json_obj)
              response = self._session.post(self._endpoint, data=data_to_send)
          else:
              response = self._session.post(self._endpoint, json=json_obj)
          response.encoding = self._encoding
          text = response.text
  
          if self._transport_enc:
              decoded_text = self.decrypt(text)
              log.debug(decoded_text)
              return json.loads(decoded_text)
          else:
              return json.loads(text)
  
      def encrypt(self, source_obj):
          encrypter = self._cipher.encryptor()
          source = json.dumps(source_obj)
          source = source.encode(self._encoding)
          need_to_padding = 16 - (len(source) % 16)
          if need_to_padding > 0:
              source = source + b'\x00' * need_to_padding
          enc_data = encrypter.update(source) + encrypter.finalize()
          b64_enc_data = base64.encodebytes(enc_data)
          return urllib.parse.quote(b64_enc_data)
  
      def decrypt(self, source):
          decrypter = self._cipher.decryptor()
          source = urllib.parse.unquote(source)
          source = base64.decodebytes(source.encode("utf-8"))
          data_bytes = decrypter.update(source) + decrypter.finalize()
          return data_bytes.rstrip(b"\x00").decode(self._encoding)
  
      def data_to_df(self, result):
          if 'data' in result:
              data = result['data']
              return pd.DataFrame(data=data)
  
      #------ functions
  
      def ping(self):
  
          return self.call("ping", {})
  
      def logon(self, ip, port, version, yyb_id, account_id, trade_account, jy_passwrod, tx_password):
          return self.call("logon",{
              "ip": ip,
              "port": port,
              "version": version,
              "yyb_id": yyb_id,
              "account_no": account_id,
              "trade_account": trade_account,
              "jy_password": jy_passwrod,
              "tx_password": tx_password
          })
  
      def logoff(self, client_id):
          return self.call("logoff", {
              "client_id": client_id
          })
  
      def query_data(self, client_id, category):
          return self.call("query_data", {
              "client_id": client_id,
              "category": category
          })
  
      def send_order(self, client_id, category, price_type, gddm, zqdm, price, quantity):
          return self.call("send_order", {
              'client_id': client_id,
              'category': category,
              'price_type': price_type,
              'gddm': gddm,
              'zqdm': zqdm,
              'price': price,
              'quantity': quantity
          })
  
      def cancel_order(self, client_id, exchange_id, hth):
          return self.call("cancel_order", {
              'client_id': client_id,
              'exchange_id': exchange_id,
              'hth': hth
          })
  
      def get_quote(self, client_id, code):
          return self.call("get_quote", {
              'client_id': client_id,
              'code': code,
          })
  
      def repay(self, client_id, amount):
          return self.call("repay", {
              'client_id': client_id,
              'amount': amount
          })
  
      def query_history_data(self, client_id, category, begin_date, end_date):
          return self.call('query_history_data', {
              'client_id': client_id,
              'category': category,
              'begin_date': begin_date,
              'end_date': end_date
          })
  
      def query_datas(self, client_id, categories):
          return self.call('query_datas', {
              'client_id': client_id,
              'categories': categories
          })
  
      def get_quotes(self, client_id, codes):
          return self.call("get_quotes", {
              'client_id': client_id,
              'zqdms': codes
          })
  
      def send_orders(self, client_id, orders):
          """
          发送订单
          :param client_id:
          :param orders:
          格式
          [
              {
                  "category": xx,
                  "price_type" :xx,
                  "price": xx,
                  "gddm": xx,
                  "zqdm": xx,
                  "quantity": xx,
              },
              {
              ....
              },
              {
              ....
              }
          ]
  
          :return:
          """
          return self.call("send_orders", {
              'client_id': client_id,
              "orders": orders
          })
  
      def cancel_orders(self, client_id, orders):
          """
          撤销订单
          :param client_id:
          :param orders:
          格式
          [
              {
                  "exchange_id": xx,
                  "hth": xx
              },
              {
              ....
              },
              {
              ....
              }
          ]
  
          :return:
          """
          return self.call("cancel_orders", {
              'client_id': client_id,
              "orders": orders
          })
  
      def get_active_clients(self):
          return self.call(func="get_active_clients")
  
  if __name__ == "__main__":
      import os
      #api = TdxTradeApi(endpoint="http://10.11.5.215:10092/api", enc_key=b"4f1cf3fec4c84c84", enc_iv=b"0c78abc083b011e7")
      api = TdxTradeApi(endpoint="http://10.11.5.215:10092/api")
      print("---Ping---")
      result = api.ping()
      print(result)
  
      print("---登入---")
      acc = os.getenv("TDX_ACCOUNT", "")
      password = os.getenv("TDX_PASS", "")
      result = api.logon("202.108.253.186", 7708,
                "8.23", 32,
                acc, acc, password, "")
  
      print(result)
  
      if result["success"]:
          client_id = result["data"]["client_id"]
  
          for i in (0,1,2,3,4,5,6,7,8,12,13,14,15):
              print("---查询信息 cate=%d--" % i)
              print(api.data_to_df(api.query_data(client_id, i)))
  
  
          print("---查询报价---")
          print(api.data_to_df(api.get_quote(client_id, '600315')))
  
          print("---批量查询报价---")
          print(api.data_to_df(api.get_quotes(client_id, ['600315', '000001'])))
  
          print("---批量查询信息")
          print(api.data_to_df(api.query_datas(client_id, [0,1,2])))
  
          print("---登出---")
          print(api.logoff(client_id))
  
  
  
  
  
  