Пример #1
0
 def I(self, func: typing.Callable, *args) -> np.ndarray:
     value = func(*args)
     value = np.asarray(value)
     utils.assert_msg(value.shape[-1] == len(self._data.Close),
                      "指示器长度必须和data长度相同")
     self._indicators.append(value)
     return value
Пример #2
0
async def create_job_for_analysis(ws,
                                  http_client,
                                  base_url,
                                  analysis_uuid,
                                  token=None):
    job_uuid = _get_uuid_str()
    job_url = f"{base_url}/api/jobs/{job_uuid}/"
    job_data = {
        "job": {
            "analysis": analysis_uuid,
        }
    }
    job_url = add_token(job_url, token)
    async with http_client.put(job_url, json=job_data) as resp:
        print(await resp.text())
        assert resp.status == 200
        resp_json = await resp.json()
        assert resp_json['status'] == "ok"

    msg = json.loads(await ws.recv())
    assert_msg(msg, 'JOB_STARTED')
    assert msg['job'] == job_uuid
    assert msg['analysis'] == analysis_uuid
    assert msg['details']['id'] == job_uuid

    return job_uuid, job_url
Пример #3
0
async def create_analysis(ws,
                          http_client,
                          base_url,
                          ds_uuid,
                          ca_uuid,
                          details=None):
    analysis_uuid = _get_uuid_str()
    analysis_url = "{}/api/compoundAnalyses/{}/analyses/{}/".format(
        base_url, ca_uuid, analysis_uuid)
    if details is None:
        details = {"analysisType": "SUM_FRAMES", "parameters": {}}
    else:
        assert "analysisType" in details
        assert "parameters" in details
    analysis_data = {
        "dataset": ds_uuid,
        "details": details,
    }
    async with http_client.put(analysis_url, json=analysis_data) as resp:
        print(await resp.text())
        assert resp.status == 200
        resp_json = await resp.json()
        assert resp_json['status'] == "ok"

    msg = json.loads(await ws.recv())
    assert_msg(msg, 'ANALYSIS_CREATED')
    assert msg['dataset'] == ds_uuid
    assert msg['analysis'] == analysis_uuid
    assert msg['details'] == details

    return analysis_uuid, analysis_url
Пример #4
0
async def update_analysis(
    ws,
    http_client,
    base_url,
    ds_uuid,
    ca_uuid,
    analysis_uuid,
    details,
    token=None,
):
    analysis_url = "{}/api/compoundAnalyses/{}/analyses/{}/".format(
        base_url, ca_uuid, analysis_uuid)
    analysis_url = add_token(analysis_url, token)
    assert "analysisType" in details
    assert "parameters" in details
    analysis_data = {
        "dataset": ds_uuid,
        "details": details,
    }
    async with http_client.put(analysis_url, json=analysis_data) as resp:
        print(await resp.text())
        assert resp.status == 200
        resp_json = await resp.json()
        assert resp_json['status'] == "ok"

    msg = json.loads(await ws.recv())
    assert_msg(msg, 'ANALYSIS_UPDATED')
    assert msg['dataset'] == ds_uuid
    assert msg['analysis'] == analysis_uuid
    assert msg['details'] == details
Пример #5
0
async def test_cancel_unknown_job(default_raw, base_url, http_client,
                                  server_port):
    conn_url = "{}/api/config/connection/".format(base_url)
    conn_details = {
        'connection': {
            'type': 'local',
            'numWorkers': 2,
        }
    }
    async with http_client.put(conn_url, json=conn_details) as response:
        assert response.status == 200
        assert (await response.json())['status'] == 'ok'

    # connect to ws endpoint:
    ws_url = "ws://127.0.0.1:{}/api/events/".format(server_port)
    async with websockets.connect(ws_url) as ws:
        initial_msg = json.loads(await ws.recv())
        assert_msg(initial_msg, 'INITIAL_STATE')

        job_uuid = "un-kn-ow-n"
        job_url = "{}/api/jobs/{}/".format(base_url, job_uuid)

        # try to cancel unknown job:
        async with http_client.delete(job_url) as resp:
            assert resp.status == 200
            assert_msg(await resp.json(), 'CANCEL_JOB_FAILED', status='error')
Пример #6
0
async def test_detect_failed(default_raw, base_url, http_client, server_port):
    conn_url = "{}/api/config/connection/".format(base_url)
    conn_details = {
        'connection': {
            'type': 'local',
            'numWorkers': 2,
        }
    }
    async with http_client.put(conn_url, json=conn_details) as response:
        assert response.status == 200

    # connect to ws endpoint:
    ws_url = "ws://127.0.0.1:{}/api/events/".format(server_port)
    async with websockets.connect(ws_url) as ws:
        initial_msg = json.loads(await ws.recv())
        assert_msg(initial_msg, 'INITIAL_STATE')
        assert initial_msg['datasets'] == []
        assert initial_msg['jobs'] == []

        path = default_raw._path
        detect_url = "{}/api/datasets/detect/".format(base_url)

        async with http_client.get(detect_url, params={"path": path}) as resp:
            assert resp.status == 200
            resp_json = await resp.json()
            assert_msg(resp_json, 'DATASET_DETECTION_FAILED', status='error')
Пример #7
0
async def test_load_raw_fail(default_raw, base_url, http_client):
    conn_url = "{}/api/config/connection/".format(base_url)
    conn_details = {
        'connection': {
            'type': 'local',
            'numWorkers': 2,
        }
    }
    async with http_client.put(conn_url, json=conn_details) as response:
        assert response.status == 200

    raw_path = default_raw._path

    uuid = "ae5d23bd-1f2a-4c57-bab2-dfc59a1219f3"
    ds_url = "{}/api/datasets/{}/".format(base_url, uuid)
    ds_data = _get_raw_params(raw_path)
    ds_data["dataset"]["params"]["scan_size"] = [
        32, 32
    ]  # too large, should cause error
    async with http_client.put(ds_url, json=ds_data) as resp:
        assert resp.status == 200
        resp_json = await resp.json()
        assert_msg(resp_json, 'CREATE_DATASET_ERROR', status='error')
        assert resp_json['dataset'] == uuid
        assert resp_json['msg'].startswith('invalid dataset: ')
Пример #8
0
    def __init__(self,
                 data: pd.DataFrame,
                 strategy_type: type(Strategy),
                 broker_type: type(ExchangeAPI),
                 cash: float = 1000,
                 commission: float = .0):

        utils.assert_msg(issubclass(strategy_type, Strategy),
                         "strategy_type 不是一个Strategy类型")
        utils.assert_msg(issubclass(broker_type, ExchangeAPI),
                         "broker_type 不是一个ExchangeAPI类型")
        utils.assert_msg(isinstance(commission, numbers.Number),
                         "commission 不是浮点型")

        data = data.copy(False)
        if "Volume" not in data:
            data["Volume"] = np.nan

        utils.assert_msg(
            len(data.columns
                & {"Open", "High", "Low", "Close", "Volume"}) == 5,
            "输入的 `data` 格式不正确")

        utils.assert_msg(
            not data[["Open", "High", "Low", "Close", "Volume"
                      ]].max().isnull().any(), "部分 OHLC 包含缺失值 ")

        if not data.index.is_monotonic_increasing:
            data = data.sort_index()

        self._data = data
        self._broker = broker_type(data, cash, commission)
        self._strategy = strategy_type(self._broker, self._data)
        self._results = None
Пример #9
0
 def I(self, func: Callable, *args) -> np.ndarray:
     value = func(*args)
     value = np.asarray(value)
     assert_msg(value.shape[-1] == len(self._data.Close),
                'The length of indicator must equal to that of data!')
     self._indicators.append(value)
     return value
Пример #10
0
async def test_cancel_unknown_job(
    default_raw,
    base_url,
    http_client,
    server_port,
    local_cluster_url,
    default_token,
):
    await create_connection(
        base_url,
        http_client,
        scheduler_url=local_cluster_url,
        token=default_token,
    )

    ws_url = f"ws://127.0.0.1:{server_port}/api/events/?token={default_token}"
    async with websockets.connect(ws_url) as ws:
        initial_msg = json.loads(await ws.recv())
        assert_msg(initial_msg, 'INITIAL_STATE')

        job_uuid = "un-kn-ow-n"
        job_url = f"{base_url}/api/jobs/{job_uuid}/?token={default_token}"

        # try to cancel unknown job:
        async with http_client.delete(job_url) as resp:
            assert resp.status == 200
            assert_msg(await resp.json(), 'CANCEL_JOB_FAILED', status='error')
Пример #11
0
async def test_detect_hdf5(hdf5, base_url, http_client, server_port):
    conn_url = "{}/api/config/connection/".format(base_url)
    conn_details = {
        'connection': {
            'type': 'local',
            'numWorkers': 2,
        }
    }
    async with http_client.put(conn_url, json=conn_details) as response:
        assert response.status == 200

    # connect to ws endpoint:
    ws_url = "ws://127.0.0.1:{}/api/events/".format(server_port)
    async with websockets.connect(ws_url) as ws:
        initial_msg = json.loads(await ws.recv())
        assert_msg(initial_msg, 'INITIAL_STATE')
        assert initial_msg['datasets'] == []
        assert initial_msg['jobs'] == []

        path = hdf5.filename
        detect_url = "{}/api/datasets/detect/".format(base_url)

        async with http_client.get(detect_url, params={"path": path}) as resp:
            assert resp.status == 200
            resp_json = await resp.json()
            assert_msg(resp_json, 'DATASET_DETECTED')
            assert "datasetParams" in resp_json
            params = resp_json["datasetParams"]
            assert params['type'] == 'HDF5'
            assert params['path'] == path
            assert params['ds_path'] == "data"
            assert "tileshape" in params
Пример #12
0
 def __init__(self, data, cash, commission):
     assert_msg(0 < cash, "初始现金数量大于0,输入的现金数量:{}".format(cash))
     assert_msg(0 <= commission <= 0.05, "合理的手续费率一般不会超过5%,输入的费率:{}".format(commission))
     self._initial_cash = cash
     self._data = data
     self._commission = commission
     self._position = 0
     self._cash = cash
     self._i = 0
Пример #13
0
 def __init__(self, data, cash, commission):
     assert_msg(0 < cash, "initial cash deposite amount must be bigger than 0,please type the amount:{}".format(cash))
     assert_msg(0 <= commission <= 0.05, "reasonable commission fee should usually be less than 5%,please type the rate:{}".format(commission))
     self._inital_cash = cash
     self._data = data
     self._commission = commission
     self._position = 0
     self._cash = cash
     self._i = 0
Пример #14
0
async def test_shutdown(base_url, http_client, server_port):
    await create_connection(base_url, http_client)

    print("checkpoint 1")

    url = f"ws://127.0.0.1:{server_port}/api/shutdown/"
    async with http_client.delete(url) as resp:
        print("checkpoint 2")
        assert resp.status == 200
        assert_msg(await resp.json(), "SERVER_SHUTDOWN")
Пример #15
0
    def __init__(self,
                 data: pd.DataFrame,
                 strategy_type: type(Strategy),
                 broker_type: type(ExchangeAPI),
                 cash: float = 10000,
                 commission: float = .0):
        """
        构造回测对象。需要的参数包括:历史数据,策略对象,初始资金数量,手续费率等。
        初始化过程包括检测输入类型,填充数据空值等。

        参数:
        :param data:            pd.DataFrame            pandas Dataframe格式的历史OHLCV数据
        :param broker_type:     type(ExchangeAPI)       交易所API类型,负责执行买卖操作以及账户状态的维护
        :param strategy_type:   type(Strategy)          策略类型
        :param cash:            float                   初始资金数量
        :param commission:      float                   每次交易手续费率。如2%的手续费此处为0.02
        """

        assert_msg(issubclass(strategy_type, Strategy),
                   'strategy_type不是一个Strategy类型')
        assert_msg(issubclass(broker_type, ExchangeAPI),
                   'broker_type不是一个ExchangeAPI类型')
        assert_msg(isinstance(commission, float), 'commission不是浮点数值类型')

        self._strategy_value = []
        self._strategy_return = []

        data = data.copy(False)

        # 如果没有Volumn列,填充NaN
        if 'Volume' not in data:
            data['Volume'] = np.nan

        # 验证OHLC数据格式
        assert_msg(
            len(data.columns
                & {'Open', 'High', 'Low', 'Close', 'Volume'}) == 5,
            ("输入的`data`格式不正确,至少需要包含这些列:"
             ""
             "'Open', 'High', 'Low', 'Close'"))

        # 检查缺失值
        assert_msg(
            not data[['Open', 'High', 'Low', 'Close']].max().isnull().any(),
            ('部分OHLC包含缺失值,请去掉那些行或者通过差值填充. '))

        # 如果行情数据没有按照时间排序,重新排序一下
        if not data.index.is_monotonic_increasing:
            data = data.sort_index()

        # 利用数据,初始化交易所对象和策略对象。
        self._data = data  # type: pd.DataFrame
        self._broker = broker_type(data, cash, commission)
        self._strategy = strategy_type(self._broker, self._data)
        self._results = None
Пример #16
0
    def __init__(self, data, cash, commission):
        utils.assert_msg(0 < cash, "初始资金大于0,输入的现金数量:{}".format(cash))
        utils.assert_msg(0 <= commission <= 0.05,
                         "合理的手续费不超过5%,输入的费率:{}".format(commission))

        self._init_cash = cash
        self._data = data
        self._commission = commission
        self._position = 0
        self._cash = cash
        self._i = 0
Пример #17
0
 def __init__(self, data, cash, commission):
     assert_msg(cash > 0, 'Initial cash must be greater than 0!')
     assert_msg(
         0 <= commission <= 0.05,
         'Commission must be a positive integer which is usually smaller that 0.05'
     )
     self._initial_cash = cash
     self._cash = cash
     self._position = 0
     self._data = data
     self._commission = commission
     self._i = 0
Пример #18
0
 def __init__(self, data, cash, commission):
     utils.assert_msg(0 < cash,
                      "初始现金数量须大于0,输入现金数量: {}".format(cash))
     utils.assert_msg(0 <= commission <= 0.05,
                      "合理的手续费率一般不会超过5%,输入的费率:{"
                      "}".format(commission))
     self._initial_cash = cash
     self._data = data
     self._commission = commission
     self._position = 0
     self._cash = cash
     self._i = 0
Пример #19
0
async def test_cluster_connect_error(base_url, http_client):
    url = "{}/api/config/connection/".format(base_url)
    conn_details = {
        'connection': {
            'type': 'TCP',
            'address': 'tcp://invalid',
        }
    }
    async with http_client.put(url, json=conn_details) as response:
        assert response.status == 200
        conn_resp = await response.json()
        assert_msg(conn_resp, 'CLUSTER_CONN_ERROR', status='error')
Пример #20
0
async def test_initial_state_w_existing_ds(
    default_raw, base_url, http_client, server_port, local_cluster_url, default_token,
):
    conn_url = f"{base_url}/api/config/connection/?token={default_token}"
    conn_details = {
        'connection': {
            'type': 'tcp',
            'address': local_cluster_url,
        }
    }
    async with http_client.put(conn_url, json=conn_details) as response:
        assert response.status == 200

    # first connect has empty list of datasets:
    ws_url = f"ws://127.0.0.1:{server_port}/api/events/?token={default_token}"
    async with websockets.connect(ws_url) as ws:
        initial_msg = json.loads(await ws.recv())
        assert initial_msg['messageType'] == "INITIAL_STATE"
        assert initial_msg['status'] == "ok"
        assert initial_msg['datasets'] == []

    raw_path = default_raw._path

    ds_uuid = "ae5d23bd-1f2a-4c57-bab2-dfc59a1219f3"
    ds_url = "{}/api/datasets/{}/?token={}".format(
        base_url, ds_uuid, default_token,
    )
    ds_params = _get_raw_params(raw_path)
    async with http_client.put(ds_url, json=ds_params) as resp:
        assert resp.status == 200
        resp_json = await resp.json()
        assert_msg(resp_json, 'CREATE_DATASET')
        for k in ds_params['dataset']['params']:
            assert ds_params['dataset']['params'][k] == resp_json['details']['params'][k]

    # second connect has one dataset:
    async with websockets.connect(ws_url) as ws:
        initial_msg = json.loads(await ws.recv())
        assert initial_msg['messageType'] == "INITIAL_STATE"
        assert initial_msg['status'] == "ok"
        assert len(initial_msg['datasets']) == 1
        assert initial_msg['datasets'][0]["id"] == ds_uuid
        assert initial_msg['datasets'][0]["params"] == {
            "type": "RAW",
            "path": raw_path,
            "dtype": "float32",
            "sig_shape": [128, 128],
            "enable_direct": False,
            "nav_shape": [16, 16],
            "shape": [16, 16, 128, 128],
            "sync_offset": 0
        }
Пример #21
0
    def __init__(self,
                 data: pd.DataFrame,
                 strategy_type: type(Strategy),
                 broker_type: type(ExchangeAPI),
                 cash: float = 10000,
                 commission: float = .0):
        """
        Construct a backtest object.

        Parameters:
        :param data:            pd.DataFrame        OHLCV data in pandas Dataframe format
        :param broker_type:     type(ExchangeAPI)   API type of the exchange
        :param strategy_type:   type(Strategy)      Type of the strategy
        :param cash:            float               Initial cash amount
        :param commission:       float              Process fee amount percentage
        """

        assert_msg(issubclass(strategy_type, Strategy),
                   'strategy_type is not an instance of Strategy class')
        assert_msg(issubclass(broker_type, ExchangeAPI),
                   'strategy_type is not an instance of Strategy class')
        assert_msg(isinstance(commission, Number),
                   'commission is not an instance of float class')

        data = data.copy(False)

        if 'Volume' not in data:
            data['Volume'] = np.nan

        # validate OHLC
        assert_msg(
            len(data.columns
                & {'Open', 'High', 'Low', 'Close', 'Volume'}) == 5,
            ("The input data is not in the correct format. It should at least include the following columns:"
             "'Open', 'High', 'Low', 'Close'"))

        # check for null values
        assert_msg(
            not data[['Open', 'High', 'Low', 'Close']].max().isnull().any(),
            ('Part of OHLC data has null values, please remove or interpolate those. '
             ))

        # sort based on time
        if not data.index.is_monotonic_increasing:
            data = data.sort_index()

        # initialize exchange and strategy
        self._data = data  # type: pd.DataFrame
        self._broker = broker_type(data, cash, commission)
        self._strategy = strategy_type(self._broker, self._data)
        self._results = None
Пример #22
0
async def test_load_raw_success(default_raw, base_url, http_client):
    await create_connection(base_url, http_client)
    raw_path = default_raw._path

    uuid = "ae5d23bd-1f2a-4c57-bab2-dfc59a1219f3"
    ds_url = "{}/api/datasets/{}/".format(base_url, uuid)
    ds_data = _get_raw_params(raw_path)
    async with http_client.put(ds_url, json=ds_data) as resp:
        assert resp.status == 200
        resp_json = await resp.json()
        assert_msg(resp_json, 'CREATE_DATASET')
        for k in ds_data['dataset']['params']:
            assert ds_data['dataset']['params'][k] == resp_json['details'][
                'params'][k]
Пример #23
0
async def create_default_dataset(default_raw, ws, http_client, base_url):
    ds_uuid = _get_uuid_str()
    ds_url = "{}/api/datasets/{}/".format(base_url, ds_uuid)
    ds_data = _get_raw_params(default_raw._path)
    async with http_client.put(ds_url, json=ds_data) as resp:
        assert resp.status == 200
        resp_json = await resp.json()
        assert_msg(resp_json, 'CREATE_DATASET')

    # same msg via ws:
    msg = json.loads(await ws.recv())
    assert_msg(msg, 'CREATE_DATASET')

    return ds_uuid, ds_url
Пример #24
0
async def test_load_raw_fail(default_raw, base_url, http_client):
    await create_connection(base_url, http_client)

    uuid = "ae5d23bd-1f2a-4c57-bab2-dfc59a1219f3"
    ds_url = "{}/api/datasets/{}/".format(base_url, uuid)
    ds_data = _get_raw_params("/does/not/exist/")
    async with http_client.put(ds_url, json=ds_data) as resp:
        assert resp.status == 200
        resp_json = await resp.json()
        assert_msg(resp_json, 'CREATE_DATASET_ERROR', status='error')
        assert resp_json['dataset'] == uuid
        assert ("No such file or directory" in resp_json['msg']
                or "The system cannot find the path specified"
                in resp_json['msg'])
Пример #25
0
    def I(self, func: Callable, *args) -> np.ndarray:
        """
        计算买卖指标向量。买卖指标向量是一个数组,长度和历史数据对应;
        用于判定这个时间点上需要进行"买"还是"卖"。
        例如计算滑动平均:
        def init():
            self.sma = self.I(utils.SMA, self.data.Close, N)
        """
        value = func(*args)
        value = np.asarray(value)
        assert_msg(value.shape[-1] == len(self._data.Close), '指标长度必须和data长度相同')

        self._indicators.append(value)
        return value
Пример #26
0
async def create_update_compound_analysis(
    ws,
    http_client,
    base_url,
    ds_uuid,
    details=None,
    ca_uuid=None,
    token=None,
):
    if ca_uuid is None:
        ca_uuid = _get_uuid_str()
        creating = True
    else:
        creating = False
    ca_url = f"{base_url}/api/compoundAnalyses/{ca_uuid}/"
    ca_url = add_token(ca_url, token)

    if details is None:
        details = {
            "mainType": "APPLY_RING_MASK",
            "analyses": [],
        }
    else:
        assert "analyses" in details
        assert "mainType" in details

    ca_data = {
        "dataset": ds_uuid,
        "details": details,
    }

    print("dispatching PUT request...")

    async with http_client.put(ca_url, json=ca_data) as resp:
        print(await resp.text())

        assert resp.status == 200
        resp_json = await resp.json()
        assert resp_json['status'] == "ok"

    msg = json.loads(await ws.recv())
    if creating:
        assert_msg(msg, 'COMPOUND_ANALYSIS_CREATED')
    else:
        assert_msg(msg, 'COMPOUND_ANALYSIS_UPDATED')
    assert msg['dataset'] == ds_uuid
    assert msg['compoundAnalysis'] == ca_uuid
    assert msg['details'] == details

    return ca_uuid, ca_url
Пример #27
0
    def __init__(self,
                 data: pd.DataFrame,  # pandas Dataframe格式的历史OHLCV数据
                 strategy_type: type(Strategy),  # 交易所API类型,负责执行买卖操作以及账户状态的维护
                 broker_type: type(ExchangeAPI),  # 策略类型
                 cash: float = 10000,  # 初始资金数量
                 commission: float = .0):  # 每次交易手续费率。如2%的手续费此处为0.02
        utils.assert_msg(issubclass(strategy_type, Strategy),
                         "strategy_type不是一个Strategy类型")
        utils.assert_msg(issubclass(broker_type, ExchangeAPI),
                         "broker_type不是一个ExchangeAPI类型")
        utils.assert_msg(isinstance(commission, Number),
                         "commission不是浮点类型数值")
        # False代表浅复制,没有内存拷贝
        data = data.copy(False)

        # 如果没有Volume列,填充NaN
        if "Volume" not in data:
            data["Volume"] = numpy.nan

        # 验证OHLC数据格式
        utils.assert_msg(len(data.columns &
                             {"Open", "High", "Low", "Close", "Volume"}) == 5,
                         "部分OHLC包含缺失值,请去掉那些行或者通过差值填充.")

        # 如果行情数据没有按时间排序,重新排序一下
        if not data.index.is_monotonic_increasing:
            data = data.sort_index()

        # 利用数据,初始化交易所对象和策略对象
        self._data = data
        self._broker = broker_type(data, cash, commission)
        self._strategy = strategy_type(self._broker, self._data)
        self._results = None
Пример #28
0
 def __init__(self, data, cash, commission):
     assert_msg(
         0 < cash,
         "Initial cash amount should be bigger than zero, the input is::{}".
         format(cash))
     assert_msg(
         0 <= commission <= 0.05,
         "A reasonbable process fee is typically lower than 5%, the input is: {}"
         .format(commission))
     self._inital_cash = cash
     self._data = data
     self._commission = commission
     self._position = 0
     self._cash = cash
     self._i = 0
Пример #29
0
async def test_cancel_unknown_job(default_raw, base_url, http_client, server_port):
    await create_connection(base_url, http_client)

    ws_url = "ws://127.0.0.1:{}/api/events/".format(server_port)
    async with websockets.connect(ws_url) as ws:
        initial_msg = json.loads(await ws.recv())
        assert_msg(initial_msg, 'INITIAL_STATE')

        job_uuid = "un-kn-ow-n"
        job_url = "{}/api/jobs/{}/".format(base_url, job_uuid)

        # try to cancel unknown job:
        async with http_client.delete(job_url) as resp:
            assert resp.status == 200
            assert_msg(await resp.json(), 'CANCEL_JOB_FAILED', status='error')
Пример #30
0
    def __exchange(self, symbol, amount, price, side, Extype):
        """
        :param symbol: string   Example: 'btcusd"
        :param amount: string   Example: '1'
        :param price:  string   Example: '9400'
        :param side:   string   Example: 'buy' or 'side'
        :param type:   string   Example: 'exchange limit'
        :return:
        """
        assert_msg(type(symbol) == str, 'symbol不是一个str类型')
        assert_msg(type(amount) == str, 'amount不是一个str类型')
        assert_msg(type(price) == str, 'price不是一个str类型')
        assert_msg(type(side) == str, 'side不是一个str类型')
        assert_msg(type(Extype) == str, 'Extype不是一个str类型')

        t = datetime.datetime.now()
        payload_nonce = str(int(time.mktime(t.timetuple())))
        time.sleep(1)

        url = self._base_url + self._exendpoint
        payload = {
            "request": "/v1/order/new",
            "nonce": payload_nonce,
            "symbol": symbol,
            "amount": amount,
            "price": price,
            "side": side,
            "type": Extype,
        }

        encoded_payload = json.dumps(payload).encode()
        b64 = base64.b64encode(encoded_payload)
        signature = hmac.new(self.__gemini_api_secret, b64,
                             hashlib.sha384).hexdigest()

        request_headers = {
            'Content-Type': "text/plain",
            'Content-Length': "0",
            'X-GEMINI-APIKEY': self.__gemini_api_key,
            'X-GEMINI-PAYLOAD': b64,
            'X-GEMINI-SIGNATURE': signature,
            'Cache-Control': "no-cache"
        }

        response = requests.post(url, data=None, headers=request_headers)

        #assert_msg(type(response) == list, response)
        new_clearing_order = response.json()