增加交易策略、交易指标、量化库代码等文件夹

This commit is contained in:
Win_home
2025-04-27 15:54:09 +08:00
parent ca3b209096
commit f57150dae8
589 changed files with 854346 additions and 1757 deletions

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,636 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#88\n",
"# 888\n",
"# 889\n",
"# 99, IF99"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Download data "
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"from datetime import datetime\n",
"from typing import List, Dict, Tuple\n",
"\n",
"from vnpy.trader.engine import BaseEngine, MainEngine, EventEngine\n",
"from vnpy.trader.constant import Interval, Exchange\n",
"from vnpy.trader.object import BarData, HistoryRequest\n",
"from vnpy.trader.database import database_manager\n",
"from vnpy.trader.rqdata import rqdata_client"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"rqdata_client.init()"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [],
"source": [
"def download_data(symbol, exchange):\n",
" start = datetime(2006,1,1)\n",
" req = HistoryRequest(\n",
" symbol=symbol,\n",
" exchange=exchange,\n",
" interval=Interval.DAILY,\n",
" start=start,\n",
" end=datetime.now()\n",
" )\n",
"\n",
" data = rqdata_client.query_history(req)\n",
" database_manager.save_bar_data(data)\n",
" \n",
" print(\"finish! symbol=\",symbol, \"count=\", len(data))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"download_data(\"IC99\", Exchange.CFFEX)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"database_manager.save_bar_data(data)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# GET ALL instuments"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>order_book_id</th>\n",
" <th>underlying_symbol</th>\n",
" <th>market_tplus</th>\n",
" <th>symbol</th>\n",
" <th>margin_rate</th>\n",
" <th>maturity_date</th>\n",
" <th>type</th>\n",
" <th>trading_code</th>\n",
" <th>exchange</th>\n",
" <th>product</th>\n",
" <th>contract_multiplier</th>\n",
" <th>round_lot</th>\n",
" <th>trading_hours</th>\n",
" <th>listed_date</th>\n",
" <th>industry_name</th>\n",
" <th>de_listed_date</th>\n",
" <th>underlying_order_book_id</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>A0303</td>\n",
" <td>A</td>\n",
" <td>0.0</td>\n",
" <td>豆一0303</td>\n",
" <td>0.05</td>\n",
" <td>2003-03-14</td>\n",
" <td>Future</td>\n",
" <td>a0303</td>\n",
" <td>DCE</td>\n",
" <td>Commodity</td>\n",
" <td>10.0</td>\n",
" <td>1.0</td>\n",
" <td>21:01-23:00,09:01-10:15,10:31-11:30,13:31-15:00</td>\n",
" <td>2002-03-15</td>\n",
" <td>油脂</td>\n",
" <td>2003-03-14</td>\n",
" <td>null</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>A0305</td>\n",
" <td>A</td>\n",
" <td>0.0</td>\n",
" <td>豆一0305</td>\n",
" <td>0.05</td>\n",
" <td>2003-05-23</td>\n",
" <td>Future</td>\n",
" <td>a0305</td>\n",
" <td>DCE</td>\n",
" <td>Commodity</td>\n",
" <td>10.0</td>\n",
" <td>1.0</td>\n",
" <td>21:01-23:00,09:01-10:15,10:31-11:30,13:31-15:00</td>\n",
" <td>2002-03-15</td>\n",
" <td>油脂</td>\n",
" <td>2003-05-23</td>\n",
" <td>null</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>A0307</td>\n",
" <td>A</td>\n",
" <td>0.0</td>\n",
" <td>豆一0307</td>\n",
" <td>0.05</td>\n",
" <td>2003-07-14</td>\n",
" <td>Future</td>\n",
" <td>a0307</td>\n",
" <td>DCE</td>\n",
" <td>Commodity</td>\n",
" <td>10.0</td>\n",
" <td>1.0</td>\n",
" <td>21:01-23:00,09:01-10:15,10:31-11:30,13:31-15:00</td>\n",
" <td>2002-03-15</td>\n",
" <td>油脂</td>\n",
" <td>2003-07-14</td>\n",
" <td>null</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>A0309</td>\n",
" <td>A</td>\n",
" <td>0.0</td>\n",
" <td>豆一0309</td>\n",
" <td>0.05</td>\n",
" <td>2003-09-12</td>\n",
" <td>Future</td>\n",
" <td>a0309</td>\n",
" <td>DCE</td>\n",
" <td>Commodity</td>\n",
" <td>10.0</td>\n",
" <td>1.0</td>\n",
" <td>21:01-23:00,09:01-10:15,10:31-11:30,13:31-15:00</td>\n",
" <td>2002-05-22</td>\n",
" <td>油脂</td>\n",
" <td>2003-09-12</td>\n",
" <td>null</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>A0311</td>\n",
" <td>A</td>\n",
" <td>0.0</td>\n",
" <td>豆一0311</td>\n",
" <td>0.05</td>\n",
" <td>2003-11-14</td>\n",
" <td>Future</td>\n",
" <td>a0311</td>\n",
" <td>DCE</td>\n",
" <td>Commodity</td>\n",
" <td>10.0</td>\n",
" <td>1.0</td>\n",
" <td>21:01-23:00,09:01-10:15,10:31-11:30,13:31-15:00</td>\n",
" <td>2002-05-22</td>\n",
" <td>油脂</td>\n",
" <td>2003-11-14</td>\n",
" <td>null</td>\n",
" </tr>\n",
" <tr>\n",
" <th>...</th>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>6609</th>\n",
" <td>PB2201</td>\n",
" <td>PB</td>\n",
" <td>0.0</td>\n",
" <td>铅2201</td>\n",
" <td>0.08</td>\n",
" <td>2022-01-17</td>\n",
" <td>Future</td>\n",
" <td>pb2201</td>\n",
" <td>SHFE</td>\n",
" <td>Commodity</td>\n",
" <td>5.0</td>\n",
" <td>1.0</td>\n",
" <td>21:01-01:00,09:01-10:15,10:31-11:30,13:31-15:00</td>\n",
" <td>2021-01-18</td>\n",
" <td>有色</td>\n",
" <td>2022-01-17</td>\n",
" <td>null</td>\n",
" </tr>\n",
" <tr>\n",
" <th>6610</th>\n",
" <td>BC2201</td>\n",
" <td>BC</td>\n",
" <td>0.0</td>\n",
" <td>国际铜2201</td>\n",
" <td>0.08</td>\n",
" <td>2022-01-17</td>\n",
" <td>Future</td>\n",
" <td>bc2201</td>\n",
" <td>INE</td>\n",
" <td>Commodity</td>\n",
" <td>5.0</td>\n",
" <td>1.0</td>\n",
" <td>21:01-01:00,09:01-10:15,10:31-11:30,13:31-15:00</td>\n",
" <td>2021-01-18</td>\n",
" <td>未知</td>\n",
" <td>2022-01-17</td>\n",
" <td>null</td>\n",
" </tr>\n",
" <tr>\n",
" <th>6611</th>\n",
" <td>BB2201</td>\n",
" <td>BB</td>\n",
" <td>0.0</td>\n",
" <td>细木工板2201</td>\n",
" <td>0.40</td>\n",
" <td>2022-01-17</td>\n",
" <td>Future</td>\n",
" <td>bb2201</td>\n",
" <td>DCE</td>\n",
" <td>Commodity</td>\n",
" <td>500.0</td>\n",
" <td>1.0</td>\n",
" <td>09:01-10:15,10:31-11:30,13:31-15:00</td>\n",
" <td>2021-01-18</td>\n",
" <td>建材</td>\n",
" <td>2022-01-17</td>\n",
" <td>null</td>\n",
" </tr>\n",
" <tr>\n",
" <th>6612</th>\n",
" <td>SR2201</td>\n",
" <td>SR</td>\n",
" <td>0.0</td>\n",
" <td>白砂糖2201</td>\n",
" <td>0.07</td>\n",
" <td>2022-01-14</td>\n",
" <td>Future</td>\n",
" <td>SR201</td>\n",
" <td>CZCE</td>\n",
" <td>Commodity</td>\n",
" <td>10.0</td>\n",
" <td>1.0</td>\n",
" <td>21:01-23:00,09:01-10:15,10:31-11:30,13:31-15:00</td>\n",
" <td>2021-01-18</td>\n",
" <td>软商品</td>\n",
" <td>2022-01-14</td>\n",
" <td>null</td>\n",
" </tr>\n",
" <tr>\n",
" <th>6613</th>\n",
" <td>WR2201</td>\n",
" <td>WR</td>\n",
" <td>0.0</td>\n",
" <td>线材2201</td>\n",
" <td>0.07</td>\n",
" <td>2022-01-17</td>\n",
" <td>Future</td>\n",
" <td>wr2201</td>\n",
" <td>SHFE</td>\n",
" <td>Commodity</td>\n",
" <td>10.0</td>\n",
" <td>1.0</td>\n",
" <td>09:01-10:15,10:31-11:30,13:31-15:00</td>\n",
" <td>2021-01-18</td>\n",
" <td>焦煤钢矿</td>\n",
" <td>2022-01-17</td>\n",
" <td>null</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>6614 rows × 17 columns</p>\n",
"</div>"
],
"text/plain": [
" order_book_id underlying_symbol market_tplus symbol margin_rate \\\n",
"0 A0303 A 0.0 豆一0303 0.05 \n",
"1 A0305 A 0.0 豆一0305 0.05 \n",
"2 A0307 A 0.0 豆一0307 0.05 \n",
"3 A0309 A 0.0 豆一0309 0.05 \n",
"4 A0311 A 0.0 豆一0311 0.05 \n",
"... ... ... ... ... ... \n",
"6609 PB2201 PB 0.0 铅2201 0.08 \n",
"6610 BC2201 BC 0.0 国际铜2201 0.08 \n",
"6611 BB2201 BB 0.0 细木工板2201 0.40 \n",
"6612 SR2201 SR 0.0 白砂糖2201 0.07 \n",
"6613 WR2201 WR 0.0 线材2201 0.07 \n",
"\n",
" maturity_date type trading_code exchange product \\\n",
"0 2003-03-14 Future a0303 DCE Commodity \n",
"1 2003-05-23 Future a0305 DCE Commodity \n",
"2 2003-07-14 Future a0307 DCE Commodity \n",
"3 2003-09-12 Future a0309 DCE Commodity \n",
"4 2003-11-14 Future a0311 DCE Commodity \n",
"... ... ... ... ... ... \n",
"6609 2022-01-17 Future pb2201 SHFE Commodity \n",
"6610 2022-01-17 Future bc2201 INE Commodity \n",
"6611 2022-01-17 Future bb2201 DCE Commodity \n",
"6612 2022-01-14 Future SR201 CZCE Commodity \n",
"6613 2022-01-17 Future wr2201 SHFE Commodity \n",
"\n",
" contract_multiplier round_lot \\\n",
"0 10.0 1.0 \n",
"1 10.0 1.0 \n",
"2 10.0 1.0 \n",
"3 10.0 1.0 \n",
"4 10.0 1.0 \n",
"... ... ... \n",
"6609 5.0 1.0 \n",
"6610 5.0 1.0 \n",
"6611 500.0 1.0 \n",
"6612 10.0 1.0 \n",
"6613 10.0 1.0 \n",
"\n",
" trading_hours listed_date \\\n",
"0 21:01-23:00,09:01-10:15,10:31-11:30,13:31-15:00 2002-03-15 \n",
"1 21:01-23:00,09:01-10:15,10:31-11:30,13:31-15:00 2002-03-15 \n",
"2 21:01-23:00,09:01-10:15,10:31-11:30,13:31-15:00 2002-03-15 \n",
"3 21:01-23:00,09:01-10:15,10:31-11:30,13:31-15:00 2002-05-22 \n",
"4 21:01-23:00,09:01-10:15,10:31-11:30,13:31-15:00 2002-05-22 \n",
"... ... ... \n",
"6609 21:01-01:00,09:01-10:15,10:31-11:30,13:31-15:00 2021-01-18 \n",
"6610 21:01-01:00,09:01-10:15,10:31-11:30,13:31-15:00 2021-01-18 \n",
"6611 09:01-10:15,10:31-11:30,13:31-15:00 2021-01-18 \n",
"6612 21:01-23:00,09:01-10:15,10:31-11:30,13:31-15:00 2021-01-18 \n",
"6613 09:01-10:15,10:31-11:30,13:31-15:00 2021-01-18 \n",
"\n",
" industry_name de_listed_date underlying_order_book_id \n",
"0 油脂 2003-03-14 null \n",
"1 油脂 2003-05-23 null \n",
"2 油脂 2003-07-14 null \n",
"3 油脂 2003-09-12 null \n",
"4 油脂 2003-11-14 null \n",
"... ... ... ... \n",
"6609 有色 2022-01-17 null \n",
"6610 未知 2022-01-17 null \n",
"6611 建材 2022-01-17 null \n",
"6612 软商品 2022-01-14 null \n",
"6613 焦煤钢矿 2022-01-17 null \n",
"\n",
"[6614 rows x 17 columns]"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df=rqdata_client.get_all_futures()\n",
"df\n",
"# underlying_symbol\n",
"# exchange\n",
"# listed_date"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"data_dict = df.transpose().to_dict()"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'order_book_id': 'A0303',\n",
" 'underlying_symbol': 'A',\n",
" 'market_tplus': 0.0,\n",
" 'symbol': '豆一0303',\n",
" 'margin_rate': 0.05,\n",
" 'maturity_date': '2003-03-14',\n",
" 'type': 'Future',\n",
" 'trading_code': 'a0303',\n",
" 'exchange': 'DCE',\n",
" 'product': 'Commodity',\n",
" 'contract_multiplier': 10.0,\n",
" 'round_lot': 1.0,\n",
" 'trading_hours': '21:01-23:00,09:01-10:15,10:31-11:30,13:31-15:00',\n",
" 'listed_date': '2002-03-15',\n",
" 'industry_name': '油脂',\n",
" 'de_listed_date': '2003-03-14',\n",
" 'underlying_order_book_id': 'null'}"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"data_dict[0]"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [],
"source": [
"underlying_symbols = []\n",
"vt_symbols = [] # IF99.CFFEX\n",
"for data in data_dict.values():\n",
" # 1) Filter underlying symbol \n",
" underlying = data['underlying_symbol']\n",
" if underlying not in underlying_symbols:\n",
" underlying_symbols.append(underlying)\n",
" \n",
" # 2) Filter listed date\n",
" dt_str = data[\"listed_date\"]\n",
" dt = datetime.strptime(dt_str, \"%Y-%m-%d\")\n",
" \n",
" if dt <= datetime(2016,1,1):\n",
" \n",
" vt_symbol = underlying + \"99\" + \".\" + data[\"exchange\"]\n",
" \n",
" vt_symbols.append(vt_symbol)\n",
" \n",
" \n",
" "
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"finish! symbol= A99 count= 3661\n",
"finish! symbol= AG99 count= 2121\n",
"finish! symbol= AL99 count= 3661\n",
"finish! symbol= AU99 count= 3173\n",
"finish! symbol= B99 count= 3661\n",
"finish! symbol= BB99 count= 1739\n",
"finish! symbol= BU99 count= 1781\n",
"finish! symbol= C99 count= 3661\n",
"finish! symbol= CF99 count= 3661\n",
"finish! symbol= CS99 count= 1485\n",
"finish! symbol= CU99 count= 3661\n",
"finish! symbol= ER99 count= 994\n",
"finish! symbol= FB99 count= 1739\n",
"finish! symbol= FG99 count= 1980\n",
"finish! symbol= FU99 count= 3650\n",
"finish! symbol= HC99 count= 1670\n",
"finish! symbol= I99 count= 1774\n",
"finish! symbol= IC99 count= 1409\n",
"finish! symbol= IF99 count= 2620\n",
"finish! symbol= IH99 count= 1409\n",
"finish! symbol= J99 count= 2380\n",
"finish! symbol= JD99 count= 1759\n",
"finish! symbol= JM99 count= 1909\n",
"finish! symbol= JR99 count= 1753\n",
"finish! symbol= L99 count= 3282\n",
"finish! symbol= LR99 count= 1597\n",
"finish! symbol= M99 count= 3661\n",
"finish! symbol= MA99 count= 1612\n",
"finish! symbol= ME99 count= 860\n",
"finish! symbol= NI99 count= 1422\n",
"finish! symbol= OI99 count= 2075\n",
"finish! symbol= P99 count= 3223\n",
"finish! symbol= PB99 count= 2394\n",
"finish! symbol= PM99 count= 2193\n",
"finish! symbol= PP99 count= 1685\n",
"finish! symbol= RB99 count= 2878\n",
"finish! symbol= RI99 count= 2069\n",
"finish! symbol= RM99 count= 1961\n",
"finish! symbol= RO99 count= 1444\n",
"finish! symbol= RS99 count= 1961\n",
"finish! symbol= RU99 count= 3661\n",
"finish! symbol= S99 count= 0\n",
"finish! symbol= SF99 count= 1574\n",
"finish! symbol= SM99 count= 1574\n",
"finish! symbol= SN99 count= 1422\n",
"finish! symbol= SR99 count= 3659\n",
"finish! symbol= T99 count= 1427\n",
"finish! symbol= TA99 count= 3430\n",
"finish! symbol= TC99 count= 617\n",
"finish! symbol= TF99 count= 1797\n",
"finish! symbol= V99 count= 2839\n",
"finish! symbol= WH99 count= 2069\n",
"finish! symbol= WR99 count= 2853\n",
"finish! symbol= WS99 count= 1792\n",
"finish! symbol= WT99 count= 1675\n",
"finish! symbol= Y99 count= 3658\n",
"finish! symbol= ZC99 count= 1388\n",
"finish! symbol= ZN99 count= 3368\n"
]
}
],
"source": [
"for vt_symbol in vt_symbols:\n",
" symbol, exchange =tuple(vt_symbol.split(\".\"))\n",
" download_data(symbol, Exchange(exchange))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.1"
}
},
"nbformat": 4,
"nbformat_minor": 4
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,169 @@
from typing import List, Dict
from datetime import datetime
from vnpy.app.portfolio_strategy import StrategyTemplate, StrategyEngine
from vnpy.trader.utility import BarGenerator, ArrayManager
from vnpy.trader.object import TickData, BarData
from vnpy.trader.constant import Interval
class Return10Strategy(StrategyTemplate):
""""""
author = "KeKe"
price_add_percent = 0.05 # 超价5%下单
fixed_pos_value = 3000000 # 每个合约做10万
return_period = 10
holding_period = 10
shift_period = 0
signal_ts = {}
signal_total = {}
last_tick_time: datetime = None
trade_day = 0
targets_pos = {}
show_pos = {}
symbol_cap = {}
today = None
parameters = [
"price_add_percent", "fixed_pos_value",
"return_period", "holding_period", "shift_period"
]
variables = [
"signal_ts", "signal_total",
"trade_day", "targets_pos"
]
def __init__(
self,
strategy_engine: StrategyEngine,
strategy_name: str,
vt_symbols: List[str],
setting: dict
):
""""""
super().__init__(strategy_engine, strategy_name, vt_symbols, setting)
self.bgs: Dict[str, BarGenerator] = {}
self.ams: Dict[str, ArrayManager] = {}
# Obtain contract info
for vt_symbol in self.vt_symbols:
def on_bar(bar: BarData):
""""""
pass
self.bgs[vt_symbol] = BarGenerator(on_bar)
self.ams[vt_symbol] = ArrayManager()
def on_init(self):
"""
Callback when strategy is inited.
"""
self.write_log("策略初始化")
self.load_bars(days=20, interval=Interval.DAILY)
def on_start(self):
"""
Callback when strategy is started.
"""
self.write_log("策略启动")
def on_stop(self):
"""
Callback when strategy is stopped.
"""
self.write_log("策略停止")
def on_tick(self, tick: TickData):
"""
Callback of new tick data update.
"""
if (
self.last_tick_time
and self.last_tick_time.minute != tick.datetime.minute
):
bars = {}
for vt_symbol, bg in self.bgs.items():
bars[vt_symbol] = bg.generate()
self.on_bars(bars)
bg: BarGenerator = self.bgs[tick.vt_symbol]
bg.update_tick(tick)
self.last_tick_time = tick.datetime
def on_bars(self, bars: Dict[str, BarData]):
""""""
# 1) 全撤
self.cancel_all()
# 2.3初始化am &计算时间序列
for vt_symbol, bar in bars.items():
self.today = bar.datetime.date()
am: ArrayManager = self.ams[vt_symbol]
am.update_bar(bar)
# 信号 过去10天的收益率
return10 = am.rocp(self.return_period)
# 信号>0,时序信号+1信号<0,时序信号-1
if return10 > 0:
self.signal_ts[vt_symbol] = 1
elif return10 < 0:
self.signal_ts[vt_symbol] = -1
else:
self.signal_ts[vt_symbol] = 0
today = self.today
# 4信号汇总总信号=时序信号汇总 + 横截面信号汇总
# 基于总体信号,得到目标持仓
for vt_symbol, bar in bars.items():
self.signal_total[vt_symbol] = self.signal_ts[vt_symbol]
self.targets_pos[vt_symbol] = int(
self.fixed_pos_value / bar.close_price
) * self.signal_total[vt_symbol]
# 3交易执行每隔10个交易日检查并且调仓
if self.trade_day == 0 or not (self.trade_day + self.shift_period) % self.holding_period:
pos = {}
capital = {}
for vt_symbol, bar in bars.items():
bar = bars.get(vt_symbol)
if not bar:
continue
target_pos = self.targets_pos[vt_symbol]
current_pos = self.get_pos(vt_symbol)
pos[vt_symbol] = current_pos
capital[vt_symbol] = abs(bar.close_price * current_pos)
# 计算仓位差异,当产生差异时候,才进行调整
pos_diff = target_pos - current_pos
if pos_diff > 0:
price = bar.close_price * (1 + self.price_add_percent)
if current_pos < 0:
self.cover(vt_symbol, price, pos_diff)
else:
self.buy(vt_symbol, price, pos_diff)
elif pos_diff < 0:
price = bar.close_price * (1 - self.price_add_percent)
if current_pos > 0:
self.sell(vt_symbol, price, - pos_diff)
else:
self.short(vt_symbol, price, - pos_diff)
self.show_pos[today] = pos
self.symbol_cap[today] = capital
self.trade_day += 1
self.put_event()

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,154 @@
from typing import List, Dict
from datetime import datetime
from operator import itemgetter
from vnpy.app.portfolio_strategy import StrategyTemplate, StrategyEngine
from vnpy.trader.utility import BarGenerator, ArrayManager
from vnpy.trader.object import TickData, BarData
from vnpy.trader.constant import Interval
class Macd10Strategy(StrategyTemplate):
""""""
author = "KeKe"
price_add_percent = 0.05 # 超价5%下单
fixed_pos_value = 100000 # 每个合约做100万
trade_day = 0
targets_pos = {}
macd_data = {}
target_cs = {}
target_total = {}
parameters = [
"price_add_percent",
"fixed_size",
]
variables = [
]
def __init__(
self,
strategy_engine: StrategyEngine,
strategy_name: str,
vt_symbols: List[str],
setting: dict
):
""""""
super().__init__(strategy_engine, strategy_name, vt_symbols, setting)
self.bgs: Dict[str, BarGenerator] = {}
self.ams: Dict[str, ArrayManager] = {}
self.last_tick_time: datetime = None
# Obtain contract info
for vt_symbol in self.vt_symbols:
def on_bar(bar: BarData):
""""""
pass
self.bgs[vt_symbol] = BarGenerator(on_bar)
self.ams[vt_symbol] = ArrayManager()
def on_init(self):
"""
Callback when strategy is inited.
"""
self.write_log("策略初始化")
self.load_bars(10, interval=Interval.DAILY)
def on_start(self):
"""
Callback when strategy is started.
"""
self.write_log("策略启动")
def on_stop(self):
"""
Callback when strategy is stopped.
"""
self.write_log("策略停止")
def on_tick(self, tick: TickData):
"""
Callback of new tick data update.
"""
if (
self.last_tick_time
and self.last_tick_time.minute != tick.datetime.minute
):
bars = {}
for vt_symbol, bg in self.bgs.items():
bars[vt_symbol] = bg.generate()
self.on_bars(bars)
bg: BarGenerator = self.bgs[tick.vt_symbol]
bg.update_tick(tick)
self.last_tick_time = tick.datetime
def on_bars(self, bars: Dict[str, BarData]):
""""""
# MACD指标计算
for vt_symbol, bar in bars.items():
am: ArrayManager = self.ams[vt_symbol]
am.update_bar(bar)
x, y, macd = am.macd(10, 20, 5)
self.macd_data[vt_symbol] = macd
# 按照MACD从小到大排序
sorted_l = sorted(self.macd_data.items(), key=itemgetter(1))
len_symbol = len(sorted_l) # 10
choose = int(0.25 * len_symbol) # int(2.5) =2
short_part = dict(sorted_l[:choose])
long_part = dict(sorted_l[-choose:])
not_trade_part = dict(sorted_l[choose: -choose])
for k in short_part:
self.target_cs[k] = -1
for k in long_part:
self.target_cs[k] = 1
for k in not_trade_part:
self.target_cs[k] = 0
# 信号汇总
for vt_symbol, bar in bars.items():
self.target_total[vt_symbol] = self.target_cs[vt_symbol]
self.targets_pos[vt_symbol] = int(
self.fixed_pos_value / bar.close_price
) * self.target_total[vt_symbol]
# 交易执行
if self.trade_day == 0 or not (self.trade_day + 0) % 10:
for vt_symbol in self.vt_symbols:
bar = bars.get(vt_symbol)
if not bar:
continue
target_pos = self.targets_pos[vt_symbol]
current_pos = self.get_pos(vt_symbol)
pos_diff = target_pos - current_pos
if pos_diff > 0:
price = bar.close_price * (1 + self.price_add_percent)
if current_pos < 0:
self.cover(vt_symbol, price, pos_diff)
else:
self.buy(vt_symbol, price, pos_diff)
elif pos_diff < 0:
price = bar.close_price * (1 - self.price_add_percent)
if current_pos > 0:
self.sell(vt_symbol, price, - pos_diff)
else:
self.short(vt_symbol, price, - pos_diff)
self.trade_day += 1
self.put_event()

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,224 @@
from typing import List, Dict
from datetime import datetime
from vnpy.app.portfolio_strategy import StrategyTemplate, StrategyEngine
from vnpy.trader.utility import BarGenerator, ArrayManager
from vnpy.trader.object import TickData, BarData
from vnpy.trader.constant import Interval
class DemoStrategy(StrategyTemplate):
""""""
author = "KeKe"
price_add_percent = 0.05 # 超价5%下单
fixed_pos_value = 1000000 # 每个合约做10万
atr_window = 22
atr_ma_window = 10
rsi_window = 5
rsi_entry = 16
trailing_percent = 0.8
fixed_size = 1
price_add = 5
rsi_buy = 0
rsi_sell = 0
signal_ts = {}
signal_total = {}
last_tick_time: datetime = None
last_bar_time: datetime = None
trade_day = 0
targets_pos = {}
show_pos = {}
symbol_cap = {}
window_bars = {}
today = None
parameters = [
"price_add_percent", "fixed_pos_value",
"return_period", "holding_period", "shift_period"
]
variables = [
"signal_ts", "signal_total",
"trade_day", "targets_pos"
]
def __init__(
self,
strategy_engine: StrategyEngine,
strategy_name: str,
vt_symbols: List[str],
setting: dict
):
""""""
super().__init__(strategy_engine, strategy_name, vt_symbols, setting)
self.bgs: Dict[str, BarGenerator] = {}
self.ams: Dict[str, ArrayManager] = {}
self.rsi_data: Dict[str, float] = {}
self.atr_data: Dict[str, float] = {}
self.atr_ma: Dict[str, float] = {}
self.intra_trade_high: Dict[str, float] = {}
self.intra_trade_low: Dict[str, float] = {}
self.targets: Dict[str, int] = {}
# Obtain contract info
for vt_symbol in self.vt_symbols:
self.bgs[vt_symbol] = BarGenerator(
self.on_bar,
5,
self.on_window_bar
)
self.ams[vt_symbol] = ArrayManager()
def on_init(self):
"""
Callback when strategy is inited.
"""
self.write_log("策略初始化")
self.load_bars(days=20, interval=Interval.MINUTE)
def on_start(self):
"""
Callback when strategy is started.
"""
self.write_log("策略启动")
def on_stop(self):
"""
Callback when strategy is stopped.
"""
self.write_log("策略停止")
def on_bar(bar: BarData):
""""""
pass
def on_window_bar(self, bar):
dt = bar.datetime.strftime("%Y%d%m, %H:%M")
if (
self.last_bar_time
and self.last_bar_time.minute != bar.datetime.minute
):
self.on_window_bars(self.window_bars)
self.window_bars = {}
self.window_bars[bar.vt_symbol] = bar
# print("@", dt, bar.vt_symbol, bar.close_price)
else:
# print("@@", dt, bar.vt_symbol, bar.close_price)
self.window_bars[bar.vt_symbol] = bar
self.last_bar_time = bar.datetime
def on_window_bars(self, bars):
# test
# dts = {}
# for vt_symbol, bar in bars.items():
# dt = bar.datetime.strftime("%H:%M")
# dts[bar.vt_symbol] = dt
# print("**", dts)
# return
# test
self.cancel_all()
# 更新K线计算RSI数值
for vt_symbol, bar in bars.items():
am: ArrayManager = self.ams[vt_symbol]
am.update_bar(bar)
if not am.inited:
return
atr_array = am.atr(self.atr_window, array=True)
self.atr_data[vt_symbol] = atr_array[-1]
self.atr_ma[vt_symbol] = atr_array[-self.atr_ma_window:].mean()
self.rsi_data[vt_symbol] = am.rsi(self.rsi_window)
current_pos = self.get_pos(vt_symbol)
if current_pos == 0:
self.intra_trade_high[vt_symbol] = bar.high_price
self.intra_trade_low[vt_symbol] = bar.low_price
if self.atr_data[vt_symbol] > self.atr_ma[vt_symbol]:
if self.rsi_data[vt_symbol] > self.rsi_buy:
self.targets[vt_symbol] = self.fixed_size
elif self.rsi_data[vt_symbol] < self.rsi_sell:
self.targets[vt_symbol] = -self.fixed_size
else:
self.targets[vt_symbol] = 0
elif current_pos > 0:
self.intra_trade_high[vt_symbol] = max(self.intra_trade_high[vt_symbol], bar.high_price)
self.intra_trade_low[vt_symbol] = bar.low_price
long_stop = self.intra_trade_high[vt_symbol] * (1 - self.trailing_percent / 100)
if bar.close_price <= long_stop:
self.targets[vt_symbol] = 0
elif current_pos < 0:
self.intra_trade_low[vt_symbol] = min(self.intra_trade_low[vt_symbol], bar.low_price)
self.intra_trade_high[vt_symbol] = bar.high_price
short_stop = self.intra_trade_low[vt_symbol] * (1 + self.trailing_percent / 100)
if bar.close_price >= short_stop:
self.targets[vt_symbol] = 0
for vt_symbol in self.vt_symbols:
target_pos = self.targets.get(vt_symbol, None)
if not target_pos:
continue
current_pos = self.get_pos(vt_symbol)
pos_diff = target_pos - current_pos
volume = abs(pos_diff)
bar = bars[vt_symbol]
if pos_diff > 0:
price = bar.close_price + self.price_add
if current_pos < 0:
self.cover(vt_symbol, price, volume)
else:
self.buy(vt_symbol, price, volume)
elif pos_diff < 0:
price = bar.close_price - self.price_add
if current_pos > 0:
self.sell(vt_symbol, price, volume)
else:
self.short(vt_symbol, price, volume)
self.put_event()
def on_tick(self, tick: TickData):
"""
Callback of new tick data update.
"""
if (
self.last_tick_time
and self.last_tick_time.minute != tick.datetime.minute
):
bars = {}
for vt_symbol, bg in self.bgs.items():
bars[vt_symbol] = bg.generate()
self.on_bars(bars)
bg: BarGenerator = self.bgs[tick.vt_symbol]
bg.update_tick(tick)
self.last_tick_time = tick.datetime
def on_bars(self, bars: Dict[str, BarData]):
""""""
for vt_symbol, bg in self.bgs.items():
bar = bars[vt_symbol]
bg.update_bar(bar)

View File

@@ -0,0 +1,141 @@
from typing import List, Dict
from datetime import datetime
from vnpy.app.portfolio_strategy import StrategyTemplate, StrategyEngine
from vnpy.trader.utility import BarGenerator, ArrayManager
from vnpy.trader.object import TickData, BarData
class DoubleMaStrategy(StrategyTemplate):
""""""
author = "KeKe"
fast_window = 8
slow_window = 24
price_add = 5
today = ""
daily_pos = {}
daily_close = {}
parameters = [
"fast_window",
"slow_window",
]
def __init__(
self,
strategy_engine: StrategyEngine,
strategy_name: str,
vt_symbols: List[str],
setting: dict
):
""""""
super().__init__(strategy_engine, strategy_name, vt_symbols, setting)
self.bgs: Dict[str, BarGenerator] = {}
self.ams: Dict[str, ArrayManager] = {}
self.last_tick_time: datetime = None
# Obtain contract info
for vt_symbol in self.vt_symbols:
def on_bar(bar: BarData):
""""""
pass
self.bgs[vt_symbol] = BarGenerator(on_bar)
self.ams[vt_symbol] = ArrayManager()
def on_init(self):
"""
Callback when strategy is inited.
"""
self.write_log("策略初始化")
self.load_bars(100)
def on_start(self):
"""
Callback when strategy is started.
"""
self.write_log("策略启动")
def on_stop(self):
"""
Callback when strategy is stopped.
"""
self.write_log("策略停止")
def on_tick(self, tick: TickData):
"""
Callback of new tick data update.
"""
if (
self.last_tick_time
and self.last_tick_time.minute != tick.datetime.minute
):
bars = {}
for vt_symbol, bg in self.bgs.items():
bars[vt_symbol] = bg.generate()
self.on_bars(bars)
bg: BarGenerator = self.bgs[tick.vt_symbol]
bg.update_tick(tick)
self.last_tick_time = tick.datetime
def on_bars(self, bars: Dict[str, BarData]):
""""""
# 更新K线计算
for vt_symbol, bar in bars.items():
dt_str = bar.datetime.strftime("%Y-%m-%d")
self.today = dt_str
am: ArrayManager = self.ams[vt_symbol]
am.update_bar(bar)
if not am.inited:
continue
fast_ma = am.sma(self.fast_window, array=True)
fast_ma0 = fast_ma[-1]
fast_ma1 = fast_ma[-2]
slow_ma = am.sma(self.slow_window, array=True)
slow_ma0 = slow_ma[-1]
slow_ma1 = slow_ma[-2]
cross_over = fast_ma0 > slow_ma0 and fast_ma1 < slow_ma1
cross_below = fast_ma0 < slow_ma0 and fast_ma1 > slow_ma1
pos = self.get_pos(vt_symbol)
if cross_over:
if pos == 0:
self.buy(vt_symbol, bar.close_price, 1)
elif pos < 0:
self.cover(vt_symbol, bar.close_price, 1)
self.buy(vt_symbol, bar.close_price, 1)
elif cross_below:
if pos == 0:
self.short(vt_symbol, bar.close_price, 1)
elif pos > 0:
self.sell(vt_symbol, bar.close_price, 1)
self.short(vt_symbol, bar.close_price, 1)
self.record_current_pos(bars)
self.put_event()
def record_current_pos(self, bars):
current_pos = {}
current_close = {}
for bar in bars.values():
pos = self.get_pos(bar.vt_symbol)
current_pos[bar.vt_symbol] = pos
current_close[bar.vt_symbol] = bar.close_price
today = self.today
self.daily_pos[today] = str(current_pos)
self.daily_close[today] = current_close

View File

@@ -0,0 +1,154 @@
from typing import List, Dict
from datetime import datetime
from vnpy.app.portfolio_strategy import StrategyTemplate, StrategyEngine
from vnpy.trader.utility import BarGenerator, ArrayManager
from vnpy.trader.object import TickData, BarData
from vnpy.trader.constant import Interval
class Return10Strategy(StrategyTemplate):
""""""
author = "KeKe"
price_add_percent = 0.05 # 超价5%下单
fixed_pos_value = 1000000 # 每个合约做100万
signal_ts = {}
signal_total = {}
last_tick_time: datetime = None
trade_day = 0
targets_pos = {}
parameters = [
"price_add_percent",
"fixed_size",
]
variables = [
"signal_ts", "signal_total",
"trade_day", "targets_pos"
]
def __init__(
self,
strategy_engine: StrategyEngine,
strategy_name: str,
vt_symbols: List[str],
setting: dict
):
""""""
super().__init__(strategy_engine, strategy_name, vt_symbols, setting)
self.bgs: Dict[str, BarGenerator] = {}
self.ams: Dict[str, ArrayManager] = {}
# Obtain contract info
for vt_symbol in self.vt_symbols:
def on_bar(bar: BarData):
""""""
pass
self.bgs[vt_symbol] = BarGenerator(on_bar)
self.ams[vt_symbol] = ArrayManager()
def on_init(self):
"""
Callback when strategy is inited.
"""
self.write_log("策略初始化")
self.load_bars(days=20, interval=Interval.DAILY)
def on_start(self):
"""
Callback when strategy is started.
"""
self.write_log("策略启动")
def on_stop(self):
"""
Callback when strategy is stopped.
"""
self.write_log("策略停止")
def on_tick(self, tick: TickData):
"""
Callback of new tick data update.
"""
if (
self.last_tick_time
and self.last_tick_time.minute != tick.datetime.minute
):
bars = {}
for vt_symbol, bg in self.bgs.items():
bars[vt_symbol] = bg.generate()
self.on_bars(bars)
bg: BarGenerator = self.bgs[tick.vt_symbol]
bg.update_tick(tick)
self.last_tick_time = tick.datetime
def on_bars(self, bars: Dict[str, BarData]):
""""""
# 1) 全撤
self.cancel_all()
# 2.3初始化am &计算时间序列
for vt_symbol, bar in bars.items():
am: ArrayManager = self.ams[vt_symbol]
am.update_bar(bar)
# if not am.inited:
# return
# 信号 过去10天的收益率
return10 = am.rocp(10)
# 信号>0,时序信号+1信号<0,时序信号-1
if return10 > 0:
self.signal_ts[vt_symbol] = 1
elif return10 < - 0:
self.signal_ts[vt_symbol] = -1
else:
self.signal_ts[vt_symbol] = 0
# 3信号汇总总信号=时序信号汇总 + 横截面信号汇总
# 基于总体信号,得到目标持仓
for vt_symbol, bar in bars.items():
self.signal_total[vt_symbol] = self.signal_ts[vt_symbol]
self.targets_pos[vt_symbol] = int(
self.fixed_pos_value / bar.close_price
) * self.signal_total[vt_symbol]
# 3交易执行每隔10个交易日检查并且调仓
if self.trade_day == 0 or not self.trade_day % 10:
for vt_symbol in self.vt_symbols:
bar = bars.get(vt_symbol)
if not bar:
continue
target_pos = self.targets_pos[vt_symbol]
current_pos = self.get_pos(vt_symbol)
# 计算仓位差异,当产生差异时候,才进行调整
pos_diff = target_pos - current_pos
if pos_diff > 0:
price = bar.close_price * (1 + self.price_add_percent)
if current_pos < 0:
self.cover(vt_symbol, price, pos_diff)
else:
self.buy(vt_symbol, price, pos_diff)
elif pos_diff < 0:
price = bar.close_price * (1 - self.price_add_percent)
if current_pos > 0:
self.sell(vt_symbol, price, - pos_diff)
else:
self.short(vt_symbol, price, - pos_diff)
self.trade_day += 1
self.put_event()

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,636 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#88\n",
"# 888\n",
"# 889\n",
"# 99, IF99"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Download data "
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"from datetime import datetime\n",
"from typing import List, Dict, Tuple\n",
"\n",
"from vnpy.trader.engine import BaseEngine, MainEngine, EventEngine\n",
"from vnpy.trader.constant import Interval, Exchange\n",
"from vnpy.trader.object import BarData, HistoryRequest\n",
"from vnpy.trader.database import database_manager\n",
"from vnpy.trader.rqdata import rqdata_client"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"rqdata_client.init()"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [],
"source": [
"def download_data(symbol, exchange):\n",
" start = datetime(2006,1,1)\n",
" req = HistoryRequest(\n",
" symbol=symbol,\n",
" exchange=exchange,\n",
" interval=Interval.DAILY,\n",
" start=start,\n",
" end=datetime.now()\n",
" )\n",
"\n",
" data = rqdata_client.query_history(req)\n",
" database_manager.save_bar_data(data)\n",
" \n",
" print(\"finish! symbol=\",symbol, \"count=\", len(data))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"download_data(\"IC99\", Exchange.CFFEX)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"database_manager.save_bar_data(data)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# GET ALL instuments"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>order_book_id</th>\n",
" <th>underlying_symbol</th>\n",
" <th>market_tplus</th>\n",
" <th>symbol</th>\n",
" <th>margin_rate</th>\n",
" <th>maturity_date</th>\n",
" <th>type</th>\n",
" <th>trading_code</th>\n",
" <th>exchange</th>\n",
" <th>product</th>\n",
" <th>contract_multiplier</th>\n",
" <th>round_lot</th>\n",
" <th>trading_hours</th>\n",
" <th>listed_date</th>\n",
" <th>industry_name</th>\n",
" <th>de_listed_date</th>\n",
" <th>underlying_order_book_id</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>A0303</td>\n",
" <td>A</td>\n",
" <td>0.0</td>\n",
" <td>豆一0303</td>\n",
" <td>0.05</td>\n",
" <td>2003-03-14</td>\n",
" <td>Future</td>\n",
" <td>a0303</td>\n",
" <td>DCE</td>\n",
" <td>Commodity</td>\n",
" <td>10.0</td>\n",
" <td>1.0</td>\n",
" <td>21:01-23:00,09:01-10:15,10:31-11:30,13:31-15:00</td>\n",
" <td>2002-03-15</td>\n",
" <td>油脂</td>\n",
" <td>2003-03-14</td>\n",
" <td>null</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>A0305</td>\n",
" <td>A</td>\n",
" <td>0.0</td>\n",
" <td>豆一0305</td>\n",
" <td>0.05</td>\n",
" <td>2003-05-23</td>\n",
" <td>Future</td>\n",
" <td>a0305</td>\n",
" <td>DCE</td>\n",
" <td>Commodity</td>\n",
" <td>10.0</td>\n",
" <td>1.0</td>\n",
" <td>21:01-23:00,09:01-10:15,10:31-11:30,13:31-15:00</td>\n",
" <td>2002-03-15</td>\n",
" <td>油脂</td>\n",
" <td>2003-05-23</td>\n",
" <td>null</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>A0307</td>\n",
" <td>A</td>\n",
" <td>0.0</td>\n",
" <td>豆一0307</td>\n",
" <td>0.05</td>\n",
" <td>2003-07-14</td>\n",
" <td>Future</td>\n",
" <td>a0307</td>\n",
" <td>DCE</td>\n",
" <td>Commodity</td>\n",
" <td>10.0</td>\n",
" <td>1.0</td>\n",
" <td>21:01-23:00,09:01-10:15,10:31-11:30,13:31-15:00</td>\n",
" <td>2002-03-15</td>\n",
" <td>油脂</td>\n",
" <td>2003-07-14</td>\n",
" <td>null</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>A0309</td>\n",
" <td>A</td>\n",
" <td>0.0</td>\n",
" <td>豆一0309</td>\n",
" <td>0.05</td>\n",
" <td>2003-09-12</td>\n",
" <td>Future</td>\n",
" <td>a0309</td>\n",
" <td>DCE</td>\n",
" <td>Commodity</td>\n",
" <td>10.0</td>\n",
" <td>1.0</td>\n",
" <td>21:01-23:00,09:01-10:15,10:31-11:30,13:31-15:00</td>\n",
" <td>2002-05-22</td>\n",
" <td>油脂</td>\n",
" <td>2003-09-12</td>\n",
" <td>null</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>A0311</td>\n",
" <td>A</td>\n",
" <td>0.0</td>\n",
" <td>豆一0311</td>\n",
" <td>0.05</td>\n",
" <td>2003-11-14</td>\n",
" <td>Future</td>\n",
" <td>a0311</td>\n",
" <td>DCE</td>\n",
" <td>Commodity</td>\n",
" <td>10.0</td>\n",
" <td>1.0</td>\n",
" <td>21:01-23:00,09:01-10:15,10:31-11:30,13:31-15:00</td>\n",
" <td>2002-05-22</td>\n",
" <td>油脂</td>\n",
" <td>2003-11-14</td>\n",
" <td>null</td>\n",
" </tr>\n",
" <tr>\n",
" <th>...</th>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>6609</th>\n",
" <td>PB2201</td>\n",
" <td>PB</td>\n",
" <td>0.0</td>\n",
" <td>铅2201</td>\n",
" <td>0.08</td>\n",
" <td>2022-01-17</td>\n",
" <td>Future</td>\n",
" <td>pb2201</td>\n",
" <td>SHFE</td>\n",
" <td>Commodity</td>\n",
" <td>5.0</td>\n",
" <td>1.0</td>\n",
" <td>21:01-01:00,09:01-10:15,10:31-11:30,13:31-15:00</td>\n",
" <td>2021-01-18</td>\n",
" <td>有色</td>\n",
" <td>2022-01-17</td>\n",
" <td>null</td>\n",
" </tr>\n",
" <tr>\n",
" <th>6610</th>\n",
" <td>BC2201</td>\n",
" <td>BC</td>\n",
" <td>0.0</td>\n",
" <td>国际铜2201</td>\n",
" <td>0.08</td>\n",
" <td>2022-01-17</td>\n",
" <td>Future</td>\n",
" <td>bc2201</td>\n",
" <td>INE</td>\n",
" <td>Commodity</td>\n",
" <td>5.0</td>\n",
" <td>1.0</td>\n",
" <td>21:01-01:00,09:01-10:15,10:31-11:30,13:31-15:00</td>\n",
" <td>2021-01-18</td>\n",
" <td>未知</td>\n",
" <td>2022-01-17</td>\n",
" <td>null</td>\n",
" </tr>\n",
" <tr>\n",
" <th>6611</th>\n",
" <td>BB2201</td>\n",
" <td>BB</td>\n",
" <td>0.0</td>\n",
" <td>细木工板2201</td>\n",
" <td>0.40</td>\n",
" <td>2022-01-17</td>\n",
" <td>Future</td>\n",
" <td>bb2201</td>\n",
" <td>DCE</td>\n",
" <td>Commodity</td>\n",
" <td>500.0</td>\n",
" <td>1.0</td>\n",
" <td>09:01-10:15,10:31-11:30,13:31-15:00</td>\n",
" <td>2021-01-18</td>\n",
" <td>建材</td>\n",
" <td>2022-01-17</td>\n",
" <td>null</td>\n",
" </tr>\n",
" <tr>\n",
" <th>6612</th>\n",
" <td>SR2201</td>\n",
" <td>SR</td>\n",
" <td>0.0</td>\n",
" <td>白砂糖2201</td>\n",
" <td>0.07</td>\n",
" <td>2022-01-14</td>\n",
" <td>Future</td>\n",
" <td>SR201</td>\n",
" <td>CZCE</td>\n",
" <td>Commodity</td>\n",
" <td>10.0</td>\n",
" <td>1.0</td>\n",
" <td>21:01-23:00,09:01-10:15,10:31-11:30,13:31-15:00</td>\n",
" <td>2021-01-18</td>\n",
" <td>软商品</td>\n",
" <td>2022-01-14</td>\n",
" <td>null</td>\n",
" </tr>\n",
" <tr>\n",
" <th>6613</th>\n",
" <td>WR2201</td>\n",
" <td>WR</td>\n",
" <td>0.0</td>\n",
" <td>线材2201</td>\n",
" <td>0.07</td>\n",
" <td>2022-01-17</td>\n",
" <td>Future</td>\n",
" <td>wr2201</td>\n",
" <td>SHFE</td>\n",
" <td>Commodity</td>\n",
" <td>10.0</td>\n",
" <td>1.0</td>\n",
" <td>09:01-10:15,10:31-11:30,13:31-15:00</td>\n",
" <td>2021-01-18</td>\n",
" <td>焦煤钢矿</td>\n",
" <td>2022-01-17</td>\n",
" <td>null</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>6614 rows × 17 columns</p>\n",
"</div>"
],
"text/plain": [
" order_book_id underlying_symbol market_tplus symbol margin_rate \\\n",
"0 A0303 A 0.0 豆一0303 0.05 \n",
"1 A0305 A 0.0 豆一0305 0.05 \n",
"2 A0307 A 0.0 豆一0307 0.05 \n",
"3 A0309 A 0.0 豆一0309 0.05 \n",
"4 A0311 A 0.0 豆一0311 0.05 \n",
"... ... ... ... ... ... \n",
"6609 PB2201 PB 0.0 铅2201 0.08 \n",
"6610 BC2201 BC 0.0 国际铜2201 0.08 \n",
"6611 BB2201 BB 0.0 细木工板2201 0.40 \n",
"6612 SR2201 SR 0.0 白砂糖2201 0.07 \n",
"6613 WR2201 WR 0.0 线材2201 0.07 \n",
"\n",
" maturity_date type trading_code exchange product \\\n",
"0 2003-03-14 Future a0303 DCE Commodity \n",
"1 2003-05-23 Future a0305 DCE Commodity \n",
"2 2003-07-14 Future a0307 DCE Commodity \n",
"3 2003-09-12 Future a0309 DCE Commodity \n",
"4 2003-11-14 Future a0311 DCE Commodity \n",
"... ... ... ... ... ... \n",
"6609 2022-01-17 Future pb2201 SHFE Commodity \n",
"6610 2022-01-17 Future bc2201 INE Commodity \n",
"6611 2022-01-17 Future bb2201 DCE Commodity \n",
"6612 2022-01-14 Future SR201 CZCE Commodity \n",
"6613 2022-01-17 Future wr2201 SHFE Commodity \n",
"\n",
" contract_multiplier round_lot \\\n",
"0 10.0 1.0 \n",
"1 10.0 1.0 \n",
"2 10.0 1.0 \n",
"3 10.0 1.0 \n",
"4 10.0 1.0 \n",
"... ... ... \n",
"6609 5.0 1.0 \n",
"6610 5.0 1.0 \n",
"6611 500.0 1.0 \n",
"6612 10.0 1.0 \n",
"6613 10.0 1.0 \n",
"\n",
" trading_hours listed_date \\\n",
"0 21:01-23:00,09:01-10:15,10:31-11:30,13:31-15:00 2002-03-15 \n",
"1 21:01-23:00,09:01-10:15,10:31-11:30,13:31-15:00 2002-03-15 \n",
"2 21:01-23:00,09:01-10:15,10:31-11:30,13:31-15:00 2002-03-15 \n",
"3 21:01-23:00,09:01-10:15,10:31-11:30,13:31-15:00 2002-05-22 \n",
"4 21:01-23:00,09:01-10:15,10:31-11:30,13:31-15:00 2002-05-22 \n",
"... ... ... \n",
"6609 21:01-01:00,09:01-10:15,10:31-11:30,13:31-15:00 2021-01-18 \n",
"6610 21:01-01:00,09:01-10:15,10:31-11:30,13:31-15:00 2021-01-18 \n",
"6611 09:01-10:15,10:31-11:30,13:31-15:00 2021-01-18 \n",
"6612 21:01-23:00,09:01-10:15,10:31-11:30,13:31-15:00 2021-01-18 \n",
"6613 09:01-10:15,10:31-11:30,13:31-15:00 2021-01-18 \n",
"\n",
" industry_name de_listed_date underlying_order_book_id \n",
"0 油脂 2003-03-14 null \n",
"1 油脂 2003-05-23 null \n",
"2 油脂 2003-07-14 null \n",
"3 油脂 2003-09-12 null \n",
"4 油脂 2003-11-14 null \n",
"... ... ... ... \n",
"6609 有色 2022-01-17 null \n",
"6610 未知 2022-01-17 null \n",
"6611 建材 2022-01-17 null \n",
"6612 软商品 2022-01-14 null \n",
"6613 焦煤钢矿 2022-01-17 null \n",
"\n",
"[6614 rows x 17 columns]"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df=rqdata_client.get_all_futures()\n",
"df\n",
"# underlying_symbol\n",
"# exchange\n",
"# listed_date"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"data_dict = df.transpose().to_dict()"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'order_book_id': 'A0303',\n",
" 'underlying_symbol': 'A',\n",
" 'market_tplus': 0.0,\n",
" 'symbol': '豆一0303',\n",
" 'margin_rate': 0.05,\n",
" 'maturity_date': '2003-03-14',\n",
" 'type': 'Future',\n",
" 'trading_code': 'a0303',\n",
" 'exchange': 'DCE',\n",
" 'product': 'Commodity',\n",
" 'contract_multiplier': 10.0,\n",
" 'round_lot': 1.0,\n",
" 'trading_hours': '21:01-23:00,09:01-10:15,10:31-11:30,13:31-15:00',\n",
" 'listed_date': '2002-03-15',\n",
" 'industry_name': '油脂',\n",
" 'de_listed_date': '2003-03-14',\n",
" 'underlying_order_book_id': 'null'}"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"data_dict[0]"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [],
"source": [
"underlying_symbols = []\n",
"vt_symbols = [] # IF99.CFFEX\n",
"for data in data_dict.values():\n",
" # 1) Filter underlying symbol \n",
" underlying = data['underlying_symbol']\n",
" if underlying not in underlying_symbols:\n",
" underlying_symbols.append(underlying)\n",
" \n",
" # 2) Filter listed date\n",
" dt_str = data[\"listed_date\"]\n",
" dt = datetime.strptime(dt_str, \"%Y-%m-%d\")\n",
" \n",
" if dt <= datetime(2016,1,1):\n",
" \n",
" vt_symbol = underlying + \"99\" + \".\" + data[\"exchange\"]\n",
" \n",
" vt_symbols.append(vt_symbol)\n",
" \n",
" \n",
" "
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"finish! symbol= A99 count= 3661\n",
"finish! symbol= AG99 count= 2121\n",
"finish! symbol= AL99 count= 3661\n",
"finish! symbol= AU99 count= 3173\n",
"finish! symbol= B99 count= 3661\n",
"finish! symbol= BB99 count= 1739\n",
"finish! symbol= BU99 count= 1781\n",
"finish! symbol= C99 count= 3661\n",
"finish! symbol= CF99 count= 3661\n",
"finish! symbol= CS99 count= 1485\n",
"finish! symbol= CU99 count= 3661\n",
"finish! symbol= ER99 count= 994\n",
"finish! symbol= FB99 count= 1739\n",
"finish! symbol= FG99 count= 1980\n",
"finish! symbol= FU99 count= 3650\n",
"finish! symbol= HC99 count= 1670\n",
"finish! symbol= I99 count= 1774\n",
"finish! symbol= IC99 count= 1409\n",
"finish! symbol= IF99 count= 2620\n",
"finish! symbol= IH99 count= 1409\n",
"finish! symbol= J99 count= 2380\n",
"finish! symbol= JD99 count= 1759\n",
"finish! symbol= JM99 count= 1909\n",
"finish! symbol= JR99 count= 1753\n",
"finish! symbol= L99 count= 3282\n",
"finish! symbol= LR99 count= 1597\n",
"finish! symbol= M99 count= 3661\n",
"finish! symbol= MA99 count= 1612\n",
"finish! symbol= ME99 count= 860\n",
"finish! symbol= NI99 count= 1422\n",
"finish! symbol= OI99 count= 2075\n",
"finish! symbol= P99 count= 3223\n",
"finish! symbol= PB99 count= 2394\n",
"finish! symbol= PM99 count= 2193\n",
"finish! symbol= PP99 count= 1685\n",
"finish! symbol= RB99 count= 2878\n",
"finish! symbol= RI99 count= 2069\n",
"finish! symbol= RM99 count= 1961\n",
"finish! symbol= RO99 count= 1444\n",
"finish! symbol= RS99 count= 1961\n",
"finish! symbol= RU99 count= 3661\n",
"finish! symbol= S99 count= 0\n",
"finish! symbol= SF99 count= 1574\n",
"finish! symbol= SM99 count= 1574\n",
"finish! symbol= SN99 count= 1422\n",
"finish! symbol= SR99 count= 3659\n",
"finish! symbol= T99 count= 1427\n",
"finish! symbol= TA99 count= 3430\n",
"finish! symbol= TC99 count= 617\n",
"finish! symbol= TF99 count= 1797\n",
"finish! symbol= V99 count= 2839\n",
"finish! symbol= WH99 count= 2069\n",
"finish! symbol= WR99 count= 2853\n",
"finish! symbol= WS99 count= 1792\n",
"finish! symbol= WT99 count= 1675\n",
"finish! symbol= Y99 count= 3658\n",
"finish! symbol= ZC99 count= 1388\n",
"finish! symbol= ZN99 count= 3368\n"
]
}
],
"source": [
"for vt_symbol in vt_symbols:\n",
" symbol, exchange =tuple(vt_symbol.split(\".\"))\n",
" download_data(symbol, Exchange(exchange))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.1"
}
},
"nbformat": 4,
"nbformat_minor": 4
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,169 @@
from typing import List, Dict
from datetime import datetime
from vnpy.app.portfolio_strategy import StrategyTemplate, StrategyEngine
from vnpy.trader.utility import BarGenerator, ArrayManager
from vnpy.trader.object import TickData, BarData
from vnpy.trader.constant import Interval
class Return10Strategy(StrategyTemplate):
""""""
author = "KeKe"
price_add_percent = 0.05 # 超价5%下单
fixed_pos_value = 3000000 # 每个合约做10万
return_period = 10
holding_period = 10
shift_period = 0
signal_ts = {}
signal_total = {}
last_tick_time: datetime = None
trade_day = 0
targets_pos = {}
show_pos = {}
symbol_cap = {}
today = None
parameters = [
"price_add_percent", "fixed_pos_value",
"return_period", "holding_period", "shift_period"
]
variables = [
"signal_ts", "signal_total",
"trade_day", "targets_pos"
]
def __init__(
self,
strategy_engine: StrategyEngine,
strategy_name: str,
vt_symbols: List[str],
setting: dict
):
""""""
super().__init__(strategy_engine, strategy_name, vt_symbols, setting)
self.bgs: Dict[str, BarGenerator] = {}
self.ams: Dict[str, ArrayManager] = {}
# Obtain contract info
for vt_symbol in self.vt_symbols:
def on_bar(bar: BarData):
""""""
pass
self.bgs[vt_symbol] = BarGenerator(on_bar)
self.ams[vt_symbol] = ArrayManager()
def on_init(self):
"""
Callback when strategy is inited.
"""
self.write_log("策略初始化")
self.load_bars(days=20, interval=Interval.DAILY)
def on_start(self):
"""
Callback when strategy is started.
"""
self.write_log("策略启动")
def on_stop(self):
"""
Callback when strategy is stopped.
"""
self.write_log("策略停止")
def on_tick(self, tick: TickData):
"""
Callback of new tick data update.
"""
if (
self.last_tick_time
and self.last_tick_time.minute != tick.datetime.minute
):
bars = {}
for vt_symbol, bg in self.bgs.items():
bars[vt_symbol] = bg.generate()
self.on_bars(bars)
bg: BarGenerator = self.bgs[tick.vt_symbol]
bg.update_tick(tick)
self.last_tick_time = tick.datetime
def on_bars(self, bars: Dict[str, BarData]):
""""""
# 1) 全撤
self.cancel_all()
# 2.3初始化am &计算时间序列
for vt_symbol, bar in bars.items():
self.today = bar.datetime.date()
am: ArrayManager = self.ams[vt_symbol]
am.update_bar(bar)
# 信号 过去10天的收益率
return10 = am.rocp(self.return_period)
# 信号>0,时序信号+1信号<0,时序信号-1
if return10 > 0:
self.signal_ts[vt_symbol] = 1
elif return10 < 0:
self.signal_ts[vt_symbol] = -1
else:
self.signal_ts[vt_symbol] = 0
today = self.today
# 4信号汇总总信号=时序信号汇总 + 横截面信号汇总
# 基于总体信号,得到目标持仓
for vt_symbol, bar in bars.items():
self.signal_total[vt_symbol] = self.signal_ts[vt_symbol]
self.targets_pos[vt_symbol] = int(
self.fixed_pos_value / bar.close_price
) * self.signal_total[vt_symbol]
# 3交易执行每隔10个交易日检查并且调仓
if self.trade_day == 0 or not (self.trade_day + self.shift_period) % self.holding_period:
pos = {}
capital = {}
for vt_symbol, bar in bars.items():
bar = bars.get(vt_symbol)
if not bar:
continue
target_pos = self.targets_pos[vt_symbol]
current_pos = self.get_pos(vt_symbol)
pos[vt_symbol] = current_pos
capital[vt_symbol] = abs(bar.close_price * current_pos)
# 计算仓位差异,当产生差异时候,才进行调整
pos_diff = target_pos - current_pos
if pos_diff > 0:
price = bar.close_price * (1 + self.price_add_percent)
if current_pos < 0:
self.cover(vt_symbol, price, pos_diff)
else:
self.buy(vt_symbol, price, pos_diff)
elif pos_diff < 0:
price = bar.close_price * (1 - self.price_add_percent)
if current_pos > 0:
self.sell(vt_symbol, price, - pos_diff)
else:
self.short(vt_symbol, price, - pos_diff)
self.show_pos[today] = pos
self.symbol_cap[today] = capital
self.trade_day += 1
self.put_event()

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,154 @@
from typing import List, Dict
from datetime import datetime
from operator import itemgetter
from vnpy.app.portfolio_strategy import StrategyTemplate, StrategyEngine
from vnpy.trader.utility import BarGenerator, ArrayManager
from vnpy.trader.object import TickData, BarData
from vnpy.trader.constant import Interval
class Macd10Strategy(StrategyTemplate):
""""""
author = "KeKe"
price_add_percent = 0.05 # 超价5%下单
fixed_pos_value = 100000 # 每个合约做100万
trade_day = 0
targets_pos = {}
macd_data = {}
target_cs = {}
target_total = {}
parameters = [
"price_add_percent",
"fixed_size",
]
variables = [
]
def __init__(
self,
strategy_engine: StrategyEngine,
strategy_name: str,
vt_symbols: List[str],
setting: dict
):
""""""
super().__init__(strategy_engine, strategy_name, vt_symbols, setting)
self.bgs: Dict[str, BarGenerator] = {}
self.ams: Dict[str, ArrayManager] = {}
self.last_tick_time: datetime = None
# Obtain contract info
for vt_symbol in self.vt_symbols:
def on_bar(bar: BarData):
""""""
pass
self.bgs[vt_symbol] = BarGenerator(on_bar)
self.ams[vt_symbol] = ArrayManager()
def on_init(self):
"""
Callback when strategy is inited.
"""
self.write_log("策略初始化")
self.load_bars(10, interval=Interval.DAILY)
def on_start(self):
"""
Callback when strategy is started.
"""
self.write_log("策略启动")
def on_stop(self):
"""
Callback when strategy is stopped.
"""
self.write_log("策略停止")
def on_tick(self, tick: TickData):
"""
Callback of new tick data update.
"""
if (
self.last_tick_time
and self.last_tick_time.minute != tick.datetime.minute
):
bars = {}
for vt_symbol, bg in self.bgs.items():
bars[vt_symbol] = bg.generate()
self.on_bars(bars)
bg: BarGenerator = self.bgs[tick.vt_symbol]
bg.update_tick(tick)
self.last_tick_time = tick.datetime
def on_bars(self, bars: Dict[str, BarData]):
""""""
# MACD指标计算
for vt_symbol, bar in bars.items():
am: ArrayManager = self.ams[vt_symbol]
am.update_bar(bar)
x, y, macd = am.macd(10, 20, 5)
self.macd_data[vt_symbol] = macd
# 按照MACD从小到大排序
sorted_l = sorted(self.macd_data.items(), key=itemgetter(1))
len_symbol = len(sorted_l) # 10
choose = int(0.25 * len_symbol) # int(2.5) =2
short_part = dict(sorted_l[:choose])
long_part = dict(sorted_l[-choose:])
not_trade_part = dict(sorted_l[choose: -choose])
for k in short_part:
self.target_cs[k] = -1
for k in long_part:
self.target_cs[k] = 1
for k in not_trade_part:
self.target_cs[k] = 0
# 信号汇总
for vt_symbol, bar in bars.items():
self.target_total[vt_symbol] = self.target_cs[vt_symbol]
self.targets_pos[vt_symbol] = int(
self.fixed_pos_value / bar.close_price
) * self.target_total[vt_symbol]
# 交易执行
if self.trade_day == 0 or not (self.trade_day + 0) % 10:
for vt_symbol in self.vt_symbols:
bar = bars.get(vt_symbol)
if not bar:
continue
target_pos = self.targets_pos[vt_symbol]
current_pos = self.get_pos(vt_symbol)
pos_diff = target_pos - current_pos
if pos_diff > 0:
price = bar.close_price * (1 + self.price_add_percent)
if current_pos < 0:
self.cover(vt_symbol, price, pos_diff)
else:
self.buy(vt_symbol, price, pos_diff)
elif pos_diff < 0:
price = bar.close_price * (1 - self.price_add_percent)
if current_pos > 0:
self.sell(vt_symbol, price, - pos_diff)
else:
self.short(vt_symbol, price, - pos_diff)
self.trade_day += 1
self.put_event()

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,224 @@
from typing import List, Dict
from datetime import datetime
from vnpy.app.portfolio_strategy import StrategyTemplate, StrategyEngine
from vnpy.trader.utility import BarGenerator, ArrayManager
from vnpy.trader.object import TickData, BarData
from vnpy.trader.constant import Interval
class DemoStrategy(StrategyTemplate):
""""""
author = "KeKe"
price_add_percent = 0.05 # 超价5%下单
fixed_pos_value = 1000000 # 每个合约做10万
atr_window = 22
atr_ma_window = 10
rsi_window = 5
rsi_entry = 16
trailing_percent = 0.8
fixed_size = 1
price_add = 5
rsi_buy = 0
rsi_sell = 0
signal_ts = {}
signal_total = {}
last_tick_time: datetime = None
last_bar_time: datetime = None
trade_day = 0
targets_pos = {}
show_pos = {}
symbol_cap = {}
window_bars = {}
today = None
parameters = [
"price_add_percent", "fixed_pos_value",
"return_period", "holding_period", "shift_period"
]
variables = [
"signal_ts", "signal_total",
"trade_day", "targets_pos"
]
def __init__(
self,
strategy_engine: StrategyEngine,
strategy_name: str,
vt_symbols: List[str],
setting: dict
):
""""""
super().__init__(strategy_engine, strategy_name, vt_symbols, setting)
self.bgs: Dict[str, BarGenerator] = {}
self.ams: Dict[str, ArrayManager] = {}
self.rsi_data: Dict[str, float] = {}
self.atr_data: Dict[str, float] = {}
self.atr_ma: Dict[str, float] = {}
self.intra_trade_high: Dict[str, float] = {}
self.intra_trade_low: Dict[str, float] = {}
self.targets: Dict[str, int] = {}
# Obtain contract info
for vt_symbol in self.vt_symbols:
self.bgs[vt_symbol] = BarGenerator(
self.on_bar,
5,
self.on_window_bar
)
self.ams[vt_symbol] = ArrayManager()
def on_init(self):
"""
Callback when strategy is inited.
"""
self.write_log("策略初始化")
self.load_bars(days=20, interval=Interval.MINUTE)
def on_start(self):
"""
Callback when strategy is started.
"""
self.write_log("策略启动")
def on_stop(self):
"""
Callback when strategy is stopped.
"""
self.write_log("策略停止")
def on_bar(bar: BarData):
""""""
pass
def on_window_bar(self, bar):
dt = bar.datetime.strftime("%Y%d%m, %H:%M")
if (
self.last_bar_time
and self.last_bar_time.minute != bar.datetime.minute
):
self.on_window_bars(self.window_bars)
self.window_bars = {}
self.window_bars[bar.vt_symbol] = bar
# print("@", dt, bar.vt_symbol, bar.close_price)
else:
# print("@@", dt, bar.vt_symbol, bar.close_price)
self.window_bars[bar.vt_symbol] = bar
self.last_bar_time = bar.datetime
def on_window_bars(self, bars):
# test
# dts = {}
# for vt_symbol, bar in bars.items():
# dt = bar.datetime.strftime("%H:%M")
# dts[bar.vt_symbol] = dt
# print("**", dts)
# return
# test
self.cancel_all()
# 更新K线计算RSI数值
for vt_symbol, bar in bars.items():
am: ArrayManager = self.ams[vt_symbol]
am.update_bar(bar)
if not am.inited:
return
atr_array = am.atr(self.atr_window, array=True)
self.atr_data[vt_symbol] = atr_array[-1]
self.atr_ma[vt_symbol] = atr_array[-self.atr_ma_window:].mean()
self.rsi_data[vt_symbol] = am.rsi(self.rsi_window)
current_pos = self.get_pos(vt_symbol)
if current_pos == 0:
self.intra_trade_high[vt_symbol] = bar.high_price
self.intra_trade_low[vt_symbol] = bar.low_price
if self.atr_data[vt_symbol] > self.atr_ma[vt_symbol]:
if self.rsi_data[vt_symbol] > self.rsi_buy:
self.targets[vt_symbol] = self.fixed_size
elif self.rsi_data[vt_symbol] < self.rsi_sell:
self.targets[vt_symbol] = -self.fixed_size
else:
self.targets[vt_symbol] = 0
elif current_pos > 0:
self.intra_trade_high[vt_symbol] = max(self.intra_trade_high[vt_symbol], bar.high_price)
self.intra_trade_low[vt_symbol] = bar.low_price
long_stop = self.intra_trade_high[vt_symbol] * (1 - self.trailing_percent / 100)
if bar.close_price <= long_stop:
self.targets[vt_symbol] = 0
elif current_pos < 0:
self.intra_trade_low[vt_symbol] = min(self.intra_trade_low[vt_symbol], bar.low_price)
self.intra_trade_high[vt_symbol] = bar.high_price
short_stop = self.intra_trade_low[vt_symbol] * (1 + self.trailing_percent / 100)
if bar.close_price >= short_stop:
self.targets[vt_symbol] = 0
for vt_symbol in self.vt_symbols:
target_pos = self.targets.get(vt_symbol, None)
if not target_pos:
continue
current_pos = self.get_pos(vt_symbol)
pos_diff = target_pos - current_pos
volume = abs(pos_diff)
bar = bars[vt_symbol]
if pos_diff > 0:
price = bar.close_price + self.price_add
if current_pos < 0:
self.cover(vt_symbol, price, volume)
else:
self.buy(vt_symbol, price, volume)
elif pos_diff < 0:
price = bar.close_price - self.price_add
if current_pos > 0:
self.sell(vt_symbol, price, volume)
else:
self.short(vt_symbol, price, volume)
self.put_event()
def on_tick(self, tick: TickData):
"""
Callback of new tick data update.
"""
if (
self.last_tick_time
and self.last_tick_time.minute != tick.datetime.minute
):
bars = {}
for vt_symbol, bg in self.bgs.items():
bars[vt_symbol] = bg.generate()
self.on_bars(bars)
bg: BarGenerator = self.bgs[tick.vt_symbol]
bg.update_tick(tick)
self.last_tick_time = tick.datetime
def on_bars(self, bars: Dict[str, BarData]):
""""""
for vt_symbol, bg in self.bgs.items():
bar = bars[vt_symbol]
bg.update_bar(bar)

View File

@@ -0,0 +1,141 @@
from typing import List, Dict
from datetime import datetime
from vnpy.app.portfolio_strategy import StrategyTemplate, StrategyEngine
from vnpy.trader.utility import BarGenerator, ArrayManager
from vnpy.trader.object import TickData, BarData
class DoubleMaStrategy(StrategyTemplate):
""""""
author = "KeKe"
fast_window = 8
slow_window = 24
price_add = 5
today = ""
daily_pos = {}
daily_close = {}
parameters = [
"fast_window",
"slow_window",
]
def __init__(
self,
strategy_engine: StrategyEngine,
strategy_name: str,
vt_symbols: List[str],
setting: dict
):
""""""
super().__init__(strategy_engine, strategy_name, vt_symbols, setting)
self.bgs: Dict[str, BarGenerator] = {}
self.ams: Dict[str, ArrayManager] = {}
self.last_tick_time: datetime = None
# Obtain contract info
for vt_symbol in self.vt_symbols:
def on_bar(bar: BarData):
""""""
pass
self.bgs[vt_symbol] = BarGenerator(on_bar)
self.ams[vt_symbol] = ArrayManager()
def on_init(self):
"""
Callback when strategy is inited.
"""
self.write_log("策略初始化")
self.load_bars(100)
def on_start(self):
"""
Callback when strategy is started.
"""
self.write_log("策略启动")
def on_stop(self):
"""
Callback when strategy is stopped.
"""
self.write_log("策略停止")
def on_tick(self, tick: TickData):
"""
Callback of new tick data update.
"""
if (
self.last_tick_time
and self.last_tick_time.minute != tick.datetime.minute
):
bars = {}
for vt_symbol, bg in self.bgs.items():
bars[vt_symbol] = bg.generate()
self.on_bars(bars)
bg: BarGenerator = self.bgs[tick.vt_symbol]
bg.update_tick(tick)
self.last_tick_time = tick.datetime
def on_bars(self, bars: Dict[str, BarData]):
""""""
# 更新K线计算
for vt_symbol, bar in bars.items():
dt_str = bar.datetime.strftime("%Y-%m-%d")
self.today = dt_str
am: ArrayManager = self.ams[vt_symbol]
am.update_bar(bar)
if not am.inited:
continue
fast_ma = am.sma(self.fast_window, array=True)
fast_ma0 = fast_ma[-1]
fast_ma1 = fast_ma[-2]
slow_ma = am.sma(self.slow_window, array=True)
slow_ma0 = slow_ma[-1]
slow_ma1 = slow_ma[-2]
cross_over = fast_ma0 > slow_ma0 and fast_ma1 < slow_ma1
cross_below = fast_ma0 < slow_ma0 and fast_ma1 > slow_ma1
pos = self.get_pos(vt_symbol)
if cross_over:
if pos == 0:
self.buy(vt_symbol, bar.close_price, 1)
elif pos < 0:
self.cover(vt_symbol, bar.close_price, 1)
self.buy(vt_symbol, bar.close_price, 1)
elif cross_below:
if pos == 0:
self.short(vt_symbol, bar.close_price, 1)
elif pos > 0:
self.sell(vt_symbol, bar.close_price, 1)
self.short(vt_symbol, bar.close_price, 1)
self.record_current_pos(bars)
self.put_event()
def record_current_pos(self, bars):
current_pos = {}
current_close = {}
for bar in bars.values():
pos = self.get_pos(bar.vt_symbol)
current_pos[bar.vt_symbol] = pos
current_close[bar.vt_symbol] = bar.close_price
today = self.today
self.daily_pos[today] = str(current_pos)
self.daily_close[today] = current_close

View File

@@ -0,0 +1,154 @@
from typing import List, Dict
from datetime import datetime
from vnpy.app.portfolio_strategy import StrategyTemplate, StrategyEngine
from vnpy.trader.utility import BarGenerator, ArrayManager
from vnpy.trader.object import TickData, BarData
from vnpy.trader.constant import Interval
class Return10Strategy(StrategyTemplate):
""""""
author = "KeKe"
price_add_percent = 0.05 # 超价5%下单
fixed_pos_value = 1000000 # 每个合约做100万
signal_ts = {}
signal_total = {}
last_tick_time: datetime = None
trade_day = 0
targets_pos = {}
parameters = [
"price_add_percent",
"fixed_size",
]
variables = [
"signal_ts", "signal_total",
"trade_day", "targets_pos"
]
def __init__(
self,
strategy_engine: StrategyEngine,
strategy_name: str,
vt_symbols: List[str],
setting: dict
):
""""""
super().__init__(strategy_engine, strategy_name, vt_symbols, setting)
self.bgs: Dict[str, BarGenerator] = {}
self.ams: Dict[str, ArrayManager] = {}
# Obtain contract info
for vt_symbol in self.vt_symbols:
def on_bar(bar: BarData):
""""""
pass
self.bgs[vt_symbol] = BarGenerator(on_bar)
self.ams[vt_symbol] = ArrayManager()
def on_init(self):
"""
Callback when strategy is inited.
"""
self.write_log("策略初始化")
self.load_bars(days=20, interval=Interval.DAILY)
def on_start(self):
"""
Callback when strategy is started.
"""
self.write_log("策略启动")
def on_stop(self):
"""
Callback when strategy is stopped.
"""
self.write_log("策略停止")
def on_tick(self, tick: TickData):
"""
Callback of new tick data update.
"""
if (
self.last_tick_time
and self.last_tick_time.minute != tick.datetime.minute
):
bars = {}
for vt_symbol, bg in self.bgs.items():
bars[vt_symbol] = bg.generate()
self.on_bars(bars)
bg: BarGenerator = self.bgs[tick.vt_symbol]
bg.update_tick(tick)
self.last_tick_time = tick.datetime
def on_bars(self, bars: Dict[str, BarData]):
""""""
# 1) 全撤
self.cancel_all()
# 2.3初始化am &计算时间序列
for vt_symbol, bar in bars.items():
am: ArrayManager = self.ams[vt_symbol]
am.update_bar(bar)
# if not am.inited:
# return
# 信号 过去10天的收益率
return10 = am.rocp(10)
# 信号>0,时序信号+1信号<0,时序信号-1
if return10 > 0:
self.signal_ts[vt_symbol] = 1
elif return10 < - 0:
self.signal_ts[vt_symbol] = -1
else:
self.signal_ts[vt_symbol] = 0
# 3信号汇总总信号=时序信号汇总 + 横截面信号汇总
# 基于总体信号,得到目标持仓
for vt_symbol, bar in bars.items():
self.signal_total[vt_symbol] = self.signal_ts[vt_symbol]
self.targets_pos[vt_symbol] = int(
self.fixed_pos_value / bar.close_price
) * self.signal_total[vt_symbol]
# 3交易执行每隔10个交易日检查并且调仓
if self.trade_day == 0 or not self.trade_day % 10:
for vt_symbol in self.vt_symbols:
bar = bars.get(vt_symbol)
if not bar:
continue
target_pos = self.targets_pos[vt_symbol]
current_pos = self.get_pos(vt_symbol)
# 计算仓位差异,当产生差异时候,才进行调整
pos_diff = target_pos - current_pos
if pos_diff > 0:
price = bar.close_price * (1 + self.price_add_percent)
if current_pos < 0:
self.cover(vt_symbol, price, pos_diff)
else:
self.buy(vt_symbol, price, pos_diff)
elif pos_diff < 0:
price = bar.close_price * (1 - self.price_add_percent)
if current_pos > 0:
self.sell(vt_symbol, price, - pos_diff)
else:
self.short(vt_symbol, price, - pos_diff)
self.trade_day += 1
self.put_event()