策略示例(python)

入门策略

buySellSymbol-股票买卖策略

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from xquant import *

'''
股票策略:买卖策略
本策略是一个简单的买卖策略,主要是体现如何下单的。当没有持仓时就进行买入操作,当有持仓时,就进行卖出平仓操作
回测标的:平安银行(000001.SZ)
'''
if __name__ == '__main__':
    config = {
        "user": "SDK-User",  # 点击客户端管理平台右上角用户名可查看填写
        "token": "SDK-Token",  # 点击客户端管理平台右上角用户名可查看填写
        "instance_id": "ID",  # 客户端管理平台回测记录中本策略的回测ID,点击复制ID,粘贴此处即可
        "login_endpoint": "https -h prx-01.upoem1.com -p 443",  # 登录地址

        "initialize": {
            # symbols里设置单个股票或者其他有效的标的
            "symbols": ["000001.SZ"],

            # 必填:设置所需k线类型,interval可以选取1分钟,5分钟,15分钟,30分钟,60分钟,日k,count为提前缓存的数目
            'bars': [
                {
                    'interval': '1day',
                    'count': 60,
                    'match':True
                }
            ],
            # 必填: 设置回测开始和结束日期 市场初始资金
            "backtest": {
                "start_date": 20210101,
                "end_date": 20221101,
                "cash": {'CS': 1000000},
            },
            # 选填:为group_only,则只响应on_handle_data;为single_only,则只响应on_bar;为both,则两个回调同时响应
            'mode': 'single_only',
            # 必填: 设置交易手续费
            "commission": 0.0003,
        }
    }

    xquant.run_quant(config)


# 必要:每个交易日回测/模拟/实盘前要做的操作
def on_before_market_open(api, date_now):
    # 必要:获取当个交易日需关注的股票
    # 设置今天关注的股票,如果股票池中只有一只股票,则全部关注即可;股票池中股票过多时,需要先选股在设置部分关注以提高运行效率
    api.set_focus_symbols(api.get_symbol_pool())


# 必要:每天回测/交易 策略 两种方式回调  on_bar/on_handle_data
# 用日K做回测,所以每天只会进入一次,收盘时响应此函数
# 策略逻辑:第一天买入,第二天卖出;判断逻辑,如果当前有仓位,则平仓,如果当前没有仓位,则买入
def on_bar(api, bar):
    symbol_positions = api.get_symbol_positions()  # 获取持仓标的信息
    if symbol_positions:  # 如果持仓数大于0
        # 平仓
        log.info("target position zero!")
        api.target_position(symbol=bar.symbol, qty=0,price = float(bar.close))  # 卖出 symbol = 选中标的,数量变为0
    else:
        # 限价下单
        log.info("target position 1000!")
        api.target_position(symbol=bar.symbol, qty=1000,price = float(bar.close))  # 买入 symbol = 选中标的,直至持仓数达1000股

buySellFutures-期货买卖策略

#!/usr/bin/env python
# -*- coding: utf-8 -*-

'''
期货策略:买卖策略
本策略是一个简单的期货买卖策略,主要是体现期货简单买卖
'''

from xquant import *

if __name__ == '__main__':
    config = {
        "user": "SDK-User",  # 点击客户端管理平台右上角用户名可查看填写
        "token": "SDK-Token",  # 点击客户端管理平台右上角用户名可查看填写
        "instance_id": "ID",  # 客户端管理平台回测记录中本策略的回测ID,点击复制ID,粘贴此处即可

        "login_endpoint": "https -h prx-01.upoem1.com -p 443",  # 登录地址

        # 初始化参数
        "initialize": {
            # symbol_sets里设置标的集合,如此处的IF.PRD指的就是IF品种的所有标准合约,不包含IFZ0.CFE和IFZ1.CFE
            'symbols': ['IFZ0.CFE'],
            'symbol_sets': ['IF.PRD'],

            # 设置所需k线类型,interval可以选取1分钟,5分钟,15分钟,30分钟,60分钟,日k,count为提前缓存的数目
            'bars': [
                {
                    'interval': "1day",
                    'count': 100,
                    'match':True
                }
            ],
            # 必填: 设置回测开始和结束日期 市场初始资金
            "backtest": {
                "start_date": 20200101,
                "end_date": 20221101,
                "cash": {'CF': 1000000},
            },
            # 选填:为group_only,则只响应on_handle_data;为single_only,则只响应on_bar;为both,则两个回调同时响应
            'mode': 'group_only',
            # 必填: 设置交易手续费
            "commission": 0.0003  
        }
    }

    xquant.run_quant(config)


def on_before_market_open(api, date_now):
    api.futures_code = api.get_continuous_symbol("IFZ0.CFE")  # 获得当前交易日IF主力合约代码
    api.set_focus_symbols(api.futures_code)


def on_handle_data(api, time_now):
    print(time_now)
    symbol_positions = api.get_symbol_positions()  # 获取持仓标的信息
    bars = api.get_bars_history(symbol=api.futures_code, timespan="1day", count=1)  # 获得合约当前bar数据
    factor = bars['pre_close'] / bars['open']  # 当昨日收盘价与前开盘价之比
    if symbol_positions:  # 如果有持仓
        if api.futures_code == symbol_positions[0].symbol:  # 当前持仓为主力合约
            # 止盈0.3%止损0.5%
            if symbol_positions[0].pos_high / symbol_positions[0].pos_price > 1.03 \
                    or symbol_positions[0].pos_low / symbol_positions[0].pos_price < 0.95:
                # 平仓
                print("target position 0!")  # 录入日志
                api.target_position(symbol=symbol_positions[0].symbol, qty=0, price = symbol_positions[0].pos_high,side='short')  # 卖出 ,symbol = 持仓标的,数量变为0
        # 当前持仓非主力合约 则换仓为主力合约
        else:
            print("换合约", api.futures_code)
            p_bars = api.get_bars_history(symbol=symbol_positions[0].symbol, timespan="1day", count=1)  # 获得合约当前bar数据
            api.target_position(symbol=symbol_positions[0].symbol, qty=0, price = float(p_bars['close']),side='short')
            api.target_position(symbol=api.futures_code, qty=2, price = float(bars['close']) ,side='short')
    else:
        if factor[0] < 1:
            print("target position 2")  # 非必要: 输出日志
            api.target_position(symbol=api.futures_code, qty=2, price = float(bars['close']), side='short')  # 买入 symbol = 选中标的开空,直至持仓数达2手

进阶策略

net_trade-网格交易(期货)

本策略为经典的期货日内策略(网格交易),设置不同的临界线,并分配不同的资金仓位

# coding=utf-8
from __future__ import print_function, absolute_import, unicode_literals, division
from xquant import *
import numpy as np
import pandas as pd

'''
策略基本思想:本策略为经典的期货日内策略(网格交易),设置不同的临界线,并分配不同的资金仓位。
策略交易频率:1分钟
交易或订阅标的:rb1801
回测时间:2018-12-01 到2018-12-30
'''
if __name__ == '__main__':
    config = {
        "user": "SDK-User",  # 点击客户端管理平台右上角用户名可查看填写
        "token": "SDK-Token",  # 点击客户端管理平台右上角用户名可查看填写
        "instance_id": "ID",  # 客户端管理平台回测记录中本策略的回测ID,点击复制ID,粘贴此处即可

        "login_endpoint": "https -h prx-01.upoem1.com -p 443",  # 登录地址
        "loglevel": 'DEBUG',
        "initialize": {
            # symbols里设置单个股票或者其他有效的标的
            'symbols': ['IFZ0.CFE'],
            'symbol_sets': ['IF.PRD'],
            # 设置所需k线类型,interval可以选取1分钟,5分钟,15分钟,30分钟,60分钟,日k,count为提前缓存的数目
            'bars': [
                {
                    'interval': '1min',
                    'count': 100,
                    'match':True
                },
            ],
            # 必填: 设置回测开始和结束日期 市场初始资金
            'backtest': {
                'start_date': 20181201,
                'end_date': 20181230,
                'cash': {'CF': 1000000}
            },
            # 选填:为group_only,则只响应on_handle_data;为single_only,则只响应on_bar;为both,则两个回调同时响应
            'mode': 'both',
            # 必填: 设置交易手续费
            "commission": 0.0003  

        }
    }

    xquant.run_quant(config)


def on_initialize(api):
    api.data_len = 100
    # 交易参数设定
    api.k1 = [-40.0, -3.0, -2.0, 2.0, 3.0, 40.0]
    api.weight = [0.5, 0.3, 0.0, 0.3, 0.5]
    api.trade_peroid = 60  # 每小时更新一次网格临界线
    api.minute_num = 0
    api.level = 3.0
    api.volume = []
    api.band = []


def on_before_market_open(api, date_now):
    api.tradeday = date_now
    api.trade_product = api.get_continuous_symbol("IFZ0.CFE")
    # 查询初始资金
    account = api.get_account(api.trade_product,"CF")
    api.capital = account.cash_available
    api.set_focus_symbols(api.trade_product)


def on_bar(api, bar):
    print('on_bar', bar)
    if (api.minute_num % api.trade_peroid) == 0:
        # 获取过去300个数据计算临界线
        data01 = api.get_bars_history(symbol=bar.symbol, timespan='1min', count=api.data_len)
        close = np.array(data01["close"]).tolist()
        api.band = np.mean(close) + np.array(api.k1) * np.std(close)
    # 计算网格状态
    grid = pd.cut([bar.close], api.band, labels=[0, 1, 2, 3, 4])[0]
    # 更新计算交易量
    api.volume = []
    for weight in api.weight:
        api.volume.append(lots(api, bar, weight))
    api.minute_num += 1
    # 查询持仓
    position_long = api.get_symbol_position(symbol=bar.symbol, side='long')
    position_short = api.get_symbol_position(symbol=bar.symbol, side='short')
    if not position_short.pos_qty and not position_long.pos_qty and grid != 2:
        if grid >= 3:
            api.target_position(symbol=bar.symbol, qty=api.volume[grid],price= float(bar.close), side='long')
            print("开多:", bar.symbol," qty:",api.volume[grid])
        if grid <= 1:
            api.target_position(symbol=bar.symbol, qty=api.volume[grid],price= float(bar.close), side='short')
            print("开空:", bar.symbol," qty:",api.volume[grid])
    elif position_long.pos_qty:
        if grid >= 3:
            api.target_position(symbol=bar.symbol, qty=api.volume[grid],price= float(bar.close), side='long')
            print("加多:", bar.symbol," qty:",api.volume[grid])
        elif grid == 2:
            api.target_position(symbol=bar.symbol, qty=0,price= float(bar.close), side='long')
            print("平多:", bar.symbol)
        elif grid <= 1:
            api.target_position(symbol=bar.symbol, qty=0,price= float(bar.close), side='long')
            api.target_position(symbol=bar.symbol, qty=api.volume[grid],price= float(bar.close), side='short')
            print("平多开空:", bar.symbol," qty:",api.volume[grid])
    elif position_short.pos_qty:
        if grid <= 1:
            api.target_position(symbol=bar.symbol, qty=api.volume[grid],price= float(bar.close),side='short')
            print("加空:", bar.symbol," qty:",api.volume[grid])
        elif grid == 2:
            api.target_position(symbol=bar.symbol, qty=0,price= float(bar.close),side='short')
            print("平多:", bar.symbol)
        elif grid >= 3:
            api.target_position(symbol=bar.symbol, qty=0,price= float(bar.close),side='short')
            api.target_position(symbol=bar.symbol, qty=api.volume[grid],price= float(bar.close),side='long')
            print("平空开多:", bar.symbol," qty:",api.volume[grid])


def lots(api, data, weight):
    # 获取账户资金计算下单手数
    refdata = api.get_ref_data(data.symbol)
    multiper = refdata.value_per_unit
    return (int(api.capital * api.level * weight / data.close / multiper))

intradayStockTrade-日内回转交易(股票)

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from __future__ import print_function, absolute_import, unicode_literals, division
from xquant import *
import sys
import datetime

try:
    import talib
except:
    print('请安装TA-Lib库')
    sys.exit(-1)

'''
本策略为股票日内回转交易。
1、首先买入600000.SH股票10000股底仓;
2、根据分钟数据计算MACD(12,26,9):
在MACD>0的时候买入100股;在MACD<0的时候卖出100股
3、每日操作的股票数不超过原有仓位,并于收盘前把仓位调整至开盘前的仓位
撮合周期为:600000.SH分钟数据
其他参数:按系统默认设置
'''

if __name__ == "__main__":
    # 读取配置文件并启动策略
    config = {
        "user": "SDK-User",  # 点击客户端管理平台右上角用户名可查看填写
        "token": "SDK-Token",  # 点击客户端管理平台右上角用户名可查看填写
        "instance_id": "ID",  # 客户端管理平台回测记录中本策略的回测ID,点击复制ID,粘贴此处即可

        "login_endpoint": "https -h prx-01.upoem1.com -p 443",  # 登录地址

        "initialize": {
            # symbols里设置单个股票或者其他有效的标的
            'symbols': ['600000.SH'],

            # fields缓存日频因子数据
            'fields': ['PE'],

            # 必填:设置所需k线类型,interval可以选取1分钟,5分钟,15分钟,30分钟,60分钟,日k,count为提前缓存的数目
            'bars': [
                {
                    'interval': "1min",
                    'count': 120,
                    'match':True
                }
            ],
            # 必填: 设置回测开始和结束日期 市场初始资金
            "backtest": {
                "start_date": 20200101,
                "end_date": 20221101,
                "cash": {'CS': 1000000},
            },
            # 选填:为group_only,则只响应on_handle_data;为single_only,则只响应on_bar;为both,则两个回调同时响应
            'mode': 'single_only',
            # 必填: 设置交易手续费
            "commission": 0.0003,
        }
    }

    xquant.run_quant(config)


def on_initialize(api):
    # 设置标的股票
    api.symbol = '600000.SH'
    # 底仓
    api.total = 10000
    # 用于判定第一个仓位是否成功开仓
    api.first = 0
    # 日内回转每次交易100股
    api.trade_n = 100
    # 交易日
    api.trade_date = [0, 0]
    # 每日仓位
    api.turnaround = [0, 0]
    # 用于判断是否触发了回转逻辑的计时
    api.ending = 0
    # 当日可平仓数量
    api.available_qty = 0
    api.data_len = 120  # 数据长度


def on_before_market_open(api, date_now):
    print("交易日:", date_now)
    # 每日开盘前订阅行情
    api.set_focus_symbols(api.symbol)
    print("订阅%s的行情" % api.symbol)
    # 查询当日可平仓数量
    api.available_qty = api.get_symbol_position(symbol=api.symbol, side='long')


def on_bar(api, bar):
    if api.first == 0:
        # 购买10000股'600000.SH'股票
        api.target_position(symbol=bar.symbol, qty=api.total,price = float(bar.close), side='long', remark="open new position")
        print("open in new long postion by market order:", bar.symbol)
        api.first = 1.
        api.trade_date[-1] = bar.trade_date
        # 每天的仓位操作
        api.turnaround = [0, 0]
        return

    # 更新最新的日期
    api.trade_date[0] = bar.trade_date
    # 若为新的一天,获取可用于回转的昨仓
    if api.trade_date[0] != api.trade_date[-1]:
        api.ending = 0
        api.turnaround = [0, 0]
    if api.ending == 1:
        return

    # 若有可用的昨仓则操作
    if api.total > 0 and api.available_qty.available_qty > 0:
        # 获取时间序列数据
        recent_data = api.get_bars_history(api.symbol, timespan='1min', count=api.data_len, price_mode='pre')
        # 计算MACD线
        macd = talib.MACD(recent_data['close'].values)[0][-1]
        # 根据MACD>0则开仓,小于0则平仓
        if macd > 0:
            # 多空单向操作都不能超过昨仓位,否则最后无法调回原仓位
            if api.turnaround[0] + api.trade_n < api.total:
                # 计算累计仓位
                api.turnaround[0] += api.trade_n
                volume = api.total + api.turnaround[0] - api.turnaround[1]
                api.target_position(symbol=bar.symbol, qty=volume, price= float(bar.close),side='long', remark="open new position")
                print("open in new long postion by market order:%s : %i" % (bar.symbol, api.trade_n))
        elif macd < 0:
            if api.turnaround[1] + api.trade_n < api.total:
                api.turnaround[1] += api.trade_n
                volume = api.total + api.turnaround[0] - api.turnaround[1]
                api.target_position(symbol=bar.symbol, qty=volume,price = float(bar.close), side='long', remark="close position")
                print("close long postion by market order:%s : %i" % (bar.symbol, api.trade_n))
        # 临近收盘时若仓位数不等于昨仓则回复所有仓位

        date = datetime.datetime.fromtimestamp(bar.time_stop / 1000.0)
        if int(date.timestamp()/1000000) >= 1455:
            print("收盘前回复仓位")
            symbol_position = api.get_symbol_position(symbol=api.symbol, side='long')
            if symbol_position.pos_qty != api.total:
                api.target_position(symbol=bar.symbol, qty=api.total,price = float(bar.close), side='long', remark="target position")
                print("To target position:%d" % (api.total))
                api.ending = 1
        # 更新过去的日期数据
        api.trade_date[-1] = api.trade_date[0]

results matching ""

    No results matching ""