├── .idea
├── ctpbee_indicator.iml
├── dictionaries
│ └── .xml
├── inspectionProfiles
│ └── Project_Default.xml
├── misc.xml
├── modules.xml
├── other.xml
├── vcs.xml
└── workspace.xml
├── LICENSE
├── README.md
├── customize
├── __init__.py
├── __pycache__
│ ├── __init__.cpython-37.pyc
│ └── api.cpython-37.pyc
├── api.py
└── customize.py
├── data.json
├── examples
├── atr_strategy.py
├── boll_strategy.py
├── cci_strategy.py
├── close_strategy.py
├── ema_strategy.py
├── kd_strategy.py
├── looper_example.py
├── macd_strategy.py
├── mtm_strategy.py
├── roc_strategy.py
├── rsi_strategy.py
├── sar_strategy.py
├── sma_strategy.py
├── smma_strategy.py
├── stdDev_strategy.py
├── tema_strategy.py
├── trix_strategy.py
├── wma_strategy.py
└── wr_strategy.py
├── indicator
├── __init__.py
├── __pycache__
│ ├── __init__.cpython-37.pyc
│ ├── indicator.cpython-37.pyc
│ ├── interface.cpython-37.pyc
│ ├── plot.cpython-37.pyc
│ └── readfile.cpython-37.pyc
├── indicator.py
├── interface.py
├── json
│ └── zn1912.SHFE.json
├── plot.py
├── readfile.py
└── txt
│ └── orcl-2014.txt
├── test.py
└── zn1912.SHFE.json
/.idea/ctpbee_indicator.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/.idea/dictionaries/.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/Project_Default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/other.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 ctpbee
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ctpbee_indicator
2 | ctpbee里面实现的指标库, 能让你快速实现指标的计算和拿到值
3 |
4 | ```python
5 | from indicator.interface import Indicator
6 | from ctpbee import LooperApi, Vessel
7 |
8 | class SmaStrategy(LooperApi):
9 |
10 | def __init__(self, name):
11 | super().__init__(name)
12 | self.count = 1
13 | self.pos = 0
14 |
15 | self.info = Indicator() # 3分钟bar线
16 | self.info.open_json('indicator/json/zn1912.SHFE.json') # 读取本地数据
17 |
18 | def on_bar(self, bar):
19 | info = self.info
20 | # opens是否要保存数据(默认false不保存)
21 | info.add_bar(bar)
22 | close_price = info.close
23 | # 简单移动平均 默认 15
24 | sma = info.sma()
25 | # 加权移动平均 默认30
26 | wma = info.wma()
27 | # 指数移动平均 默认12
28 | ema = info.ema()
29 | # 随机指标 默认参数 14, 3
30 | k, d = info.kd()
31 | # 相对强度指数 默认 14, 1
32 | rsi = info.rsi()
33 | # 异同移动平均线 默认 12, 20, 9
34 | macd, signal, histo = info.macd()
35 | # 威廉指标 默认 14
36 | wr = info.wr()
37 | # 布林带 默认 20 2
38 | t, m, b = info.boll()
39 | # 默认 10, 15
40 | smma = info.smma()
41 | # 真实平均范围 默认 14
42 | atr = info.atr()
43 | # 标准偏差 默认 20
44 | stdDev = info.stdDev()
45 | # 三重指数平滑移动平均 默认 15, 1
46 | trix = info.trix()
47 | # 变化率 默认 12
48 | roc = info.roc()
49 | # 动量指标 默认 12
50 | mtm = info.mtm()
51 | # 三式移动平均 默认 25
52 | tema = info.tema()
53 | # 顺势指标 cci 默认 20
54 | cci = info.cci()
55 | # 抛物线指标 sar 默认 2, 0.02, 0.20
56 | sar = info.sar()
57 | if close_price[-1] > sma[-1]:
58 | print("True")
59 | pass
60 | else:
61 | print("False")
62 | pass
63 |
64 | ```
65 | # example(简单列子)
66 |
67 | 例子一
68 | ```python
69 | import json
70 | from datetime import datetime, date
71 | from ctpbee import LooperApi, Vessel
72 | from ctpbee.constant import Direction
73 | from indicator.interface import Indicator
74 |
75 |
76 | def get_data(start, end, symbol, exchange, level):
77 | """ using rqdatac to make an example """
78 | # import rqdatac as rq
79 | # from rqdatac import get_price, id_convert
80 | # username = "license"
81 | # password = "NK-Ci7vnLsRiPPWYwxvvPYdYM90vxN60qUB5tVac2mQuvZ8f9Mq8K_nnUqVspOpi4BLTkSLgq8OQFpOOj7L" \
82 | # "t7AbdBZEBqRK74fIJH5vsaAfFQgl-tuB8l03axrW8cyN6-nBUho_6Y5VCRI63Mx_PN54nsQOpc1psIGEz" \
83 | # "gND8c6Y=bqMVlABkpSlrDNk4DgG-1QXNknJtk0Kkw2axvFDa0E_XPMqOcBxifuRa_DFI2svseXU-8A" \
84 | # "eLjchnTkeuvQkKh6nrfehVDiXjoMeq5sXgqpbgFAd4A5j2B1a0gpE3cb5kXb42n13fGwFaGris" \
85 | # "8-eKzz_jncvuAamkJEQQV0aLdiw="
86 | # host = "rqdatad-pro.ricequant.com"
87 | # port = 16011
88 | # rq.init(username, password, (host, port))
89 | # symbol_rq = id_convert(symbol)
90 | # data = get_price(symbol_rq, start_date=start, end_date=end, frequency=level, fields=None,
91 | # adjust_type='pre', skip_suspended=False, market='cn', expect_df=False)
92 | # origin = data.to_dict(orient='records')
93 | # result = []
94 | # for x in origin:
95 | # do = {}
96 | # do['open_price'] = x['open']
97 | # do['low_price'] = x['low']
98 | # do['high_price'] = x['high']
99 | # do['close_price'] = x['close']
100 | # do['datetime'] = datetime.strptime(str(x['trading_date']), "%Y-%m-%d %H:%M:%S")
101 | # do['symbol'] = symbol
102 | # do['local_symbol'] = symbol + "." + exchange
103 | # do['exchange'] = exchange
104 | # result.append(do)
105 | # return result
106 |
107 | def get_a_strategy():
108 |
109 | class SmaStrategy(LooperApi):
110 |
111 | def __init__(self, name):
112 | super().__init__(name)
113 | self.count = 1
114 | self.pos = 0
115 |
116 | self.bar_3 = Indicator() # 3分钟bar线
117 | self.bar_3.open_json('indicator/json/zn1912.SHFE.json') # 读取本地数据
118 |
119 | self.allow_max_price = 5000 # 设置价格上限 当价格达到这个就卖出 防止突然跌
120 | self.allow_low_price = 2000 # 设置价格下限 当价格低出这里就卖 防止巨亏
121 |
122 | def on_bar(self, bar):
123 | # todo: 收盘连长
124 | """ """
125 | self.bar_3.add_bar(bar)
126 | close = self.bar_3.close
127 |
128 | if self.allow_max_price < close[-1] and self.pos > 0:
129 | self.action.sell(bar.close_price, self.pos, bar)
130 |
131 | if self.allow_low_price > close[-1] and self.pos > 0:
132 | self.action.sell(bar.close_price, self.pos, bar)
133 |
134 | # 接连三天涨
135 | if close[-1] > close[-2] > close[-3]:
136 | # 没有就买
137 | if self.pos == 0:
138 | self.action.buy(bar.close_price, 1, bar)
139 |
140 | def on_trade(self, trade):
141 | if trade.direction == Direction.LONG:
142 | self.pos += trade.volume
143 | else:
144 | self.pos -= trade.volume
145 |
146 | def init_params(self, data):
147 | """"""
148 | # print("我在设置策略参数")
149 | return SmaStrategy("double_ma")
150 |
151 | def save_data_json(data):
152 | result = {"result": data}
153 |
154 | class CJsonEncoder(json.JSONEncoder):
155 | def default(self, obj):
156 | if isinstance(obj, datetime):
157 | return obj.strftime('%Y-%m-%d %H:%M:%S')
158 | elif isinstance(obj, date):
159 | return obj.strftime('%Y-%m-%d')
160 | else:
161 | return json.JSONEncoder.default(self, obj)
162 |
163 | with open("data.json", "w") as f:
164 | json.dump(result, f, cls=CJsonEncoder)
165 |
166 | def load_data():
167 | with open("data.json", "r") as f:
168 | data = json.load(f)
169 | return data.get("result")
170 |
171 | def run_main(data):
172 | vessel = Vessel()
173 | vessel.add_data(data)
174 | stra = get_a_strategy()
175 | vessel.add_strategy(stra)
176 | vessel.set_params({"looper":
177 | {"initial_capital": 100000,
178 | "commission": 0.005,
179 | "deal_pattern": "price",
180 | "size_map": {"ag1912.SHFE": 15},
181 | "today_commission": 0.005,
182 | "yesterday_commission": 0.02,
183 | "close_commission": 0.005,
184 | "slippage_sell": 0,
185 | "slippage_cover": 0,
186 | "slippage_buy": 0,
187 | "slippage_short": 0,
188 | "close_pattern": "yesterday",
189 | },
190 | "strategy": {}
191 | })
192 | vessel.run()
193 | from pprint import pprint
194 | result = vessel.get_result()
195 | pprint(result)
196 |
197 |
198 | if __name__ == '__main__':
199 | data = load_data()
200 | for x in data:
201 | x['datetime'] = datetime.strptime(str(x['datetime']), "%Y-%m-%d %H:%M:%S")
202 | run_main(data)
203 | ```
204 |
205 | 例子二
206 | ```python
207 | import json
208 | from datetime import datetime, date
209 | from ctpbee import LooperApi, Vessel
210 | from ctpbee.constant import Direction
211 | from indicator.interface import Indicator
212 |
213 | def get_data(start, end, symbol, exchange, level):
214 | """ using rqdatac to make an example """
215 | # import rqdatac as rq
216 | # from rqdatac import get_price, id_convert
217 | # username = "license"
218 | # password = "NK-Ci7vnLsRiPPWYwxvvPYdYM90vxN60qUB5tVac2mQuvZ8f9Mq8K_nnUqVspOpi4BLTkSLgq8OQFpOOj7L" \
219 | # "t7AbdBZEBqRK74fIJH5vsaAfFQgl-tuB8l03axrW8cyN6-nBUho_6Y5VCRI63Mx_PN54nsQOpc1psIGEz" \
220 | # "gND8c6Y=bqMVlABkpSlrDNk4DgG-1QXNknJtk0Kkw2axvFDa0E_XPMqOcBxifuRa_DFI2svseXU-8A" \
221 | # "eLjchnTkeuvQkKh6nrfehVDiXjoMeq5sXgqpbgFAd4A5j2B1a0gpE3cb5kXb42n13fGwFaGris" \
222 | # "8-eKzz_jncvuAamkJEQQV0aLdiw="
223 | # host = "rqdatad-pro.ricequant.com"
224 | # port = 16011
225 | # rq.init(username, password, (host, port))
226 | # symbol_rq = id_convert(symbol)
227 | # data = get_price(symbol_rq, start_date=start, end_date=end, frequency=level, fields=None,
228 | # adjust_type='pre', skip_suspended=False, market='cn', expect_df=False)
229 | # origin = data.to_dict(orient='records')
230 | # result = []
231 | # for x in origin:
232 | # do = {}
233 | # do['open_price'] = x['open']
234 | # do['low_price'] = x['low']
235 | # do['high_price'] = x['high']
236 | # do['close_price'] = x['close']
237 | # do['datetime'] = datetime.strptime(str(x['trading_date']), "%Y-%m-%d %H:%M:%S")
238 | # do['symbol'] = symbol
239 | # do['local_symbol'] = symbol + "." + exchange
240 | # do['exchange'] = exchange
241 | # result.append(do)
242 | # return result
243 |
244 | def get_a_strategy():
245 |
246 | class SmaStrategy(LooperApi):
247 |
248 | def __init__(self, name):
249 | super().__init__(name)
250 | self.count = 1
251 | self.pos = 0
252 | self.bar_3 = Indicator() # 3分钟线
253 |
254 | self.allow_max_price = 5000 # 设置价格上限 当价格达到这个就卖出 防止突然跌
255 | self.allow_low_price = 4100 # 设置价格下限 当价格低出这里就卖 防止巨亏
256 |
257 | self.bar_3.open_json('indicator/json/zn1912.SHFE.json')
258 |
259 | # self.bar_3.open_csv('indicator/txt/orcl-2014.txt')
260 |
261 | def on_bar(self, bar):
262 | # todo: 简单移动平均线
263 | """ """
264 | self.bar_3.add_bar(bar)
265 | close = self.bar_3.close
266 | # 简单移动平均线
267 | sma = self.bar_3.sma()
268 |
269 | if self.allow_max_price <= close[-1] and self.pos > 0:
270 | self.action.sell(bar.close_price, self.pos, bar)
271 |
272 | if self.allow_low_price >= close[-1] and self.pos > 0:
273 | self.action.sell(bar.close_price, self.pos, bar)
274 |
275 | # 接连两天涨 买进
276 | if close[-1] > sma[-1] and close[-2] > sma[-2]:
277 |
278 | if self.pos == 0:
279 | self.action.buy(bar.close_price, 1, bar)
280 |
281 | elif self.pos < 0:
282 | self.action.cover(bar.close_price, 1, bar)
283 | self.action.buy(bar.close_price, 1, bar)
284 | # 接连跌就卖
285 | if close[-1] < sma[-1] and close[-2] < sma[-2]:
286 | if self.pos == 0:
287 | pass
288 | elif self.pos > 0:
289 | self.action.sell(bar.close_price, 1, bar)
290 | self.action.short(bar.close_price, 1, bar)
291 |
292 | def on_trade(self, trade):
293 | if trade.direction == Direction.LONG:
294 | self.pos += trade.volume
295 | else:
296 | self.pos -= trade.volume
297 |
298 | def init_params(self, data):
299 | """"""
300 | # print("我在设置策略参数")
301 |
302 | return SmaStrategy("double_ma")
303 |
304 | def save_data_json(data):
305 | result = {"result": data}
306 |
307 | class CJsonEncoder(json.JSONEncoder):
308 | def default(self, obj):
309 | if isinstance(obj, datetime):
310 | return obj.strftime('%Y-%m-%d %H:%M:%S')
311 | elif isinstance(obj, date):
312 | return obj.strftime('%Y-%m-%d')
313 | else:
314 | return json.JSONEncoder.default(self, obj)
315 |
316 | with open("data.json", "w") as f:
317 | json.dump(result, f, cls=CJsonEncoder)
318 |
319 | def load_data():
320 | with open("data.json", "r") as f:
321 | data = json.load(f)
322 | return data.get("result")
323 |
324 | def run_main(data):
325 | vessel = Vessel()
326 | vessel.add_data(data)
327 | stra = get_a_strategy()
328 | vessel.add_strategy(stra)
329 | vessel.set_params({"looper":
330 | {"initial_capital": 100000,
331 | "commission": 0.005,
332 | "deal_pattern": "price",
333 | "size_map": {"ag1912.SHFE": 15},
334 | "today_commission": 0.005,
335 | "yesterday_commission": 0.02,
336 | "close_commission": 0.005,
337 | "slippage_sell": 0,
338 | "slippage_cover": 0,
339 | "slippage_buy": 0,
340 | "slippage_short": 0,
341 | "close_pattern": "yesterday",
342 | },
343 | "strategy": {}
344 | })
345 | vessel.run()
346 | from pprint import pprint
347 | result = vessel.get_result()
348 | pprint(result)
349 |
350 | if __name__ == '__main__':
351 | data = load_data()
352 | for x in data:
353 | x['datetime'] = datetime.strptime(str(x['datetime']), "%Y-%m-%d %H:%M:%S")
354 | run_main(data)
355 | ```
356 |
357 | 列子三
358 | ```python
359 | import json
360 | from datetime import datetime, date
361 | from ctpbee import LooperApi, Vessel
362 | from ctpbee.constant import Direction
363 | from indicator.interface import Indicator
364 |
365 | def get_data(start, end, symbol, exchange, level):
366 | """ using rqdatac to make an example """
367 | # import rqdatac as rq
368 | # from rqdatac import get_price, id_convert
369 | # username = "license"
370 | # password = "NK-Ci7vnLsRiPPWYwxvvPYdYM90vxN60qUB5tVac2mQuvZ8f9Mq8K_nnUqVspOpi4BLTkSLgq8OQFpOOj7L" \
371 | # "t7AbdBZEBqRK74fIJH5vsaAfFQgl-tuB8l03axrW8cyN6-nBUho_6Y5VCRI63Mx_PN54nsQOpc1psIGEz" \
372 | # "gND8c6Y=bqMVlABkpSlrDNk4DgG-1QXNknJtk0Kkw2axvFDa0E_XPMqOcBxifuRa_DFI2svseXU-8A" \
373 | # "eLjchnTkeuvQkKh6nrfehVDiXjoMeq5sXgqpbgFAd4A5j2B1a0gpE3cb5kXb42n13fGwFaGris" \
374 | # "8-eKzz_jncvuAamkJEQQV0aLdiw="
375 | # host = "rqdatad-pro.ricequant.com"
376 | # port = 16011
377 | # rq.init(username, password, (host, port))
378 | # symbol_rq = id_convert(symbol)
379 | # data = get_price(symbol_rq, start_date=start, end_date=end, frequency=level, fields=None,
380 | # adjust_type='pre', skip_suspended=False, market='cn', expect_df=False)
381 | # origin = data.to_dict(orient='records')
382 | # result = []
383 | # for x in origin:
384 | # do = {}
385 | # do['open_price'] = x['open']
386 | # do['low_price'] = x['low']
387 | # do['high_price'] = x['high']
388 | # do['close_price'] = x['close']
389 | # do['datetime'] = datetime.strptime(str(x['trading_date']), "%Y-%m-%d %H:%M:%S")
390 | # do['symbol'] = symbol
391 | # do['local_symbol'] = symbol + "." + exchange
392 | # do['exchange'] = exchange
393 | # result.append(do)
394 | # return result
395 |
396 | def get_a_strategy():
397 |
398 | class SmaStrategy(LooperApi):
399 |
400 | def __init__(self, name):
401 | super().__init__(name)
402 | self.count = 1
403 | self.pos = 0
404 |
405 | self.bar_3 = Indicator() # 3分钟线
406 |
407 | self.allow_max_price = 5000 # 设置价格上限 当价格达到这个就卖出 防止突然跌
408 | self.allow_low_price = 4100 # 设置价格下限 当价格低出这里就卖 防止巨亏
409 |
410 | self.bar_3.open_json('indicator/json/zn1912.SHFE.json')
411 |
412 | # self.bar_3.open_csv('indicator/txt/orcl-2014.txt')
413 |
414 | def on_bar(self, bar):
415 | # todo: 简单异同移动平均 macd
416 | """ """
417 | self.bar_3.add_bar(bar)
418 | close = self.bar_3.close
419 | # 简单异同移动平均 macd
420 | macd, signal, histo = self.bar_3.macd()
421 |
422 | if self.allow_max_price <= close[-1] and self.pos > 0:
423 | self.action.sell(bar.close_price, self.pos, bar)
424 |
425 | if self.allow_low_price >= close[-1] and self.pos > 0:
426 | self.action.sell(bar.close_price, self.pos, bar)
427 |
428 | if histo[-1] > 0:
429 | if self.pos == 0:
430 | self.action.buy(bar.close_price, 1, bar)
431 | else:
432 | if self.pos > 0:
433 | self.action.sell(bar.close_price, 1, bar)
434 | self.action.short(bar.close_price, 1, bar)
435 |
436 | def on_trade(self, trade):
437 | if trade.direction == Direction.LONG:
438 | self.pos += trade.volume
439 | else:
440 | self.pos -= trade.volume
441 |
442 | def init_params(self, data):
443 | """"""
444 | # print("我在设置策略参数")
445 |
446 | return SmaStrategy("double_ma")
447 |
448 | def save_data_json(data):
449 | result = {"result": data}
450 |
451 | class CJsonEncoder(json.JSONEncoder):
452 | def default(self, obj):
453 | if isinstance(obj, datetime):
454 | return obj.strftime('%Y-%m-%d %H:%M:%S')
455 | elif isinstance(obj, date):
456 | return obj.strftime('%Y-%m-%d')
457 | else:
458 | return json.JSONEncoder.default(self, obj)
459 |
460 | with open("data.json", "w") as f:
461 | json.dump(result, f, cls=CJsonEncoder)
462 |
463 | def load_data():
464 | with open("data.json", "r") as f:
465 | data = json.load(f)
466 | return data.get("result")
467 |
468 | def run_main(data):
469 | vessel = Vessel()
470 | vessel.add_data(data)
471 | stra = get_a_strategy()
472 | vessel.add_strategy(stra)
473 | vessel.set_params({"looper":
474 | {"initial_capital": 100000,
475 | "commission": 0.005,
476 | "deal_pattern": "price",
477 | "size_map": {"ag1912.SHFE": 15},
478 | "today_commission": 0.005,
479 | "yesterday_commission": 0.02,
480 | "close_commission": 0.005,
481 | "slippage_sell": 0,
482 | "slippage_cover": 0,
483 | "slippage_buy": 0,
484 | "slippage_short": 0,
485 | "close_pattern": "yesterday",
486 | },
487 | "strategy": {}
488 | })
489 | vessel.run()
490 | from pprint import pprint
491 | result = vessel.get_result()
492 | pprint(result)
493 |
494 | if __name__ == '__main__':
495 | data = load_data()
496 | for x in data:
497 | x['datetime'] = datetime.strptime(str(x['datetime']), "%Y-%m-%d %H:%M:%S")
498 | run_main(data)
499 | ```
500 |
--------------------------------------------------------------------------------
/customize/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ctpbee/ctpbee_indicator/d7a4d981eaf9e60b640d8f56b1bfb9b270269649/customize/__init__.py
--------------------------------------------------------------------------------
/customize/__pycache__/__init__.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ctpbee/ctpbee_indicator/d7a4d981eaf9e60b640d8f56b1bfb9b270269649/customize/__pycache__/__init__.cpython-37.pyc
--------------------------------------------------------------------------------
/customize/__pycache__/api.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ctpbee/ctpbee_indicator/d7a4d981eaf9e60b640d8f56b1bfb9b270269649/customize/__pycache__/api.cpython-37.pyc
--------------------------------------------------------------------------------
/customize/api.py:
--------------------------------------------------------------------------------
1 | from indicator.plot import Scheduler
2 |
3 |
4 | def inited():
5 | """
6 | 用户判断是否满足计算指标
7 | :return: bool
8 | """
9 | return Scheduler.inited
10 |
11 |
12 | def O():
13 | """
14 | Get open price time series.
15 | """
16 | return Scheduler.ret_open
17 |
18 |
19 | def H():
20 | """
21 | Get high price time series.
22 | """
23 | return Scheduler.ret_high
24 |
25 |
26 | def L():
27 | """
28 | Get low price time series.
29 | """
30 | return Scheduler.ret_low
31 |
32 |
33 | def C():
34 | """
35 | Get low price time series
36 | :return:
37 | """
38 | return Scheduler.ret_close
39 |
40 |
41 | def volume():
42 | """
43 | Get volume number
44 | :return:
45 | """
46 | return Scheduler.ret_volume
47 |
48 |
49 | def open_csv(file: str, start_time=None, end_time=None):
50 | """
51 | open TXT file
52 | data_type:
53 | Date,Open,High,Low,Close,Volume
54 | '2019-01-07 00:00:00', 3831.0, 3847.0, 3831.0, 3840.0, 554
55 | '2019-01-08 00:00:00', 3841.0, 3841.0, 3833.0, 3836.0, 554
56 | ...
57 | :param file: name
58 | :param start_time:
59 | :param end_time:
60 | :return:
61 | """
62 | return Scheduler.open_csv(file, start_time, end_time)
63 |
64 |
65 | def open_json(file: str, start_time=None, end_time=None):
66 | """
67 | open JSON file
68 | data_type:
69 | {"zn1912.SHFE": [
70 | ["2014-01-01", 18780.0, 18780.0, 18770.0, 18775.0, 266],
71 | ["2014-01-02", 18775.0, 18780.0, 18770.0, 18770.0, 312],
72 | ...
73 | ]
74 | }
75 | :param file: name
76 | :param start_time:
77 | :param end_time:
78 | :return:
79 | """
80 | return Scheduler.open_json(file, start_time, end_time)
81 |
82 |
83 | def open_cache(data: list):
84 | """
85 | read CACHE data
86 | data_type:
87 | [["2014-01-01", 22, 44, 55, 55, 6666], ["2014-01-02", 22, 44, 55, 55, 6666], ...]
88 | :param data:
89 | :return:
90 | """
91 | return Scheduler.open_cache(data)
92 |
93 |
94 | def add_bar(data, opens=False):
95 | """
96 | new bar push in array
97 | :param data: bar
98 | :param opens: if True save file else not save (default False)
99 | :return:
100 | """
101 | Scheduler.update_bar(data, opens)
102 |
103 |
104 | def MA(data, n=5):
105 |
106 | return Scheduler.ma(data, n)
107 |
108 |
109 | def SMA(data, n=15):
110 |
111 | return Scheduler.sma(data, n)
112 |
113 |
114 | def EMA(data, n=12, alpha=None):
115 |
116 | return Scheduler.ema(data, n, alpha)
117 |
118 |
119 | def WMA(data, n=30):
120 | return Scheduler.wma(data, n)
121 |
122 |
123 | def KD(data, n=14, f=3):
124 | return Scheduler.kd(data, n, f)
125 |
126 |
127 | def MACD(data, n=12, m=20, f=9):
128 | return Scheduler.macd(data, n, m, f)
129 |
130 |
131 | def RSI(data, n=14, l=1):
132 | return Scheduler.rsi(data, n, l)
133 |
134 |
135 | def SMMA(data, n=10, alpha=15):
136 | return Scheduler.smma(data, n, alpha)
137 |
138 |
139 | def ATR(data, n=14):
140 | return Scheduler.atr(data, n)
141 |
142 |
143 | def STD(data, n=20):
144 | return Scheduler.stdDev(data, n)
145 |
146 |
147 | def BOLL(data, n=20, m=2):
148 | return Scheduler.boll(data, n, m)
149 |
150 |
151 | def TRIX(data, n=15, m=1):
152 | return Scheduler.trix(data, n, m)
153 |
154 |
155 | def ROC(data, n=12):
156 | return Scheduler.roc(data, n)
157 |
158 |
159 | def MTM(data, n=12):
160 | return Scheduler.mtm(data, n)
161 |
162 |
163 | def TEMA(data, n=25):
164 | return Scheduler.tema(data, n)
165 |
166 |
167 | def WR(data, n=14):
168 | return Scheduler.wr(data, n)
169 |
170 |
171 | def CCI(n=20, f=0.015):
172 | return Scheduler.cci(n, f)
173 |
174 |
175 | def SAR(data, n=2, af=0.02, afmax=0.20):
176 | return Scheduler.sar(data, n, af, afmax)
177 |
178 |
179 | def HHV(data, n=10):
180 | """
181 | 在一定周期内某一项数据的最大值
182 | :param data:
183 | :param n:
184 | :return:
185 | """
186 | if data.lower() == "l" or data.lower() == "low":
187 | return max(Scheduler.ret_low[-1 - n:])
188 | elif data.lower() == "v" or data.lower() == "volume":
189 | return max(Scheduler.ret_volume[-1 - n:])
190 | elif data.lower() == "h" or data.lower() == "high":
191 | return max(Scheduler.ret_high[-1 - n:])
192 | elif data.lower() == "c" or data.lower() == "close":
193 | return max(Scheduler.ret_close[-1 - n:])
194 | else:
195 | return max(data[-1 - n:])
196 |
197 |
198 | def LLV(data, n=10):
199 | """
200 | 在一定周期内某一项数据的最小值
201 | :param data:
202 | :param n:
203 | :return:
204 | """
205 | if data.lower() == "l" or data.lower() == "low":
206 | return min(Scheduler.ret_low[-1 - n:])
207 | elif data.lower() == "v" or data.lower() == "volume":
208 | return min(Scheduler.ret_volume[-1 - n:])
209 | elif data.lower() == "h" or data.lower() == "high":
210 | return min(Scheduler.ret_high[-1 - n:])
211 | elif data.lower() == "c" or data.lower() == "close":
212 | return min(Scheduler.ret_close[-1 - n:])
213 | else:
214 | return min(data[-1 - n:])
215 |
216 |
217 | def REF(data, n=1):
218 | """
219 | 昨日收盘价 ref(c,1)表示昨天的收盘价, ref(v,1)表示昨天的成交量
220 | :param data:
221 | :param n:
222 | :return:
223 | """
224 | if data.lower() == "l" or data.lower() == "low":
225 | return Scheduler.ret_low[-1 - n]
226 | elif data.lower() == "v" or data.lower() == "volume":
227 | return Scheduler.ret_volume[-1 - n]
228 | elif data.lower() == "h" or data.lower() == "high":
229 | return Scheduler.ret_high[-1 - n]
230 | elif data.lower() == "c" or data.lower() == "close":
231 | return Scheduler.ret_close[-1 - n]
232 | else:
233 | return data[-1 - n]
234 |
235 |
236 | def CROSS(K, D):
237 | """
238 | 金叉 死叉
239 | :param K: 预信号
240 | :param D: 周转信号
241 | :return:
242 | """
243 | status = K - D
244 | return status
245 |
246 |
247 | def SUM(data, n=7):
248 | return sum(data[-n:])
249 |
250 |
251 | def ZIG(data, n):
252 | """
253 | 转向率
254 | :param data: 0:开盘价,1:最高价,2:最低价,3:收盘价,其余:数组信息
255 | :param n: 变化率
256 | :return:
257 | """
258 | if data == 0:
259 | steering_rate = (Scheduler.ret_open[-1]-Scheduler.ret_open[-2])/Scheduler.ret_open[-2]*100
260 | elif data == 1:
261 | steering_rate = (Scheduler.ret_high[-1] - Scheduler.ret_high[-2]) / Scheduler.ret_high[-2] * 100
262 | elif data == 2:
263 | steering_rate = (Scheduler.ret_low[-1] - Scheduler.ret_low[-2]) / Scheduler.ret_low[-2] * 100
264 | elif data == 3:
265 | steering_rate = (Scheduler.ret_close[-1] - Scheduler.ret_close[-2]) / Scheduler.ret_close[-2] * 100
266 | else:
267 | steering_rate = (data[-1]-data[-2])/data[-2]
268 | if steering_rate > n:
269 | return True
270 | else:
271 | return False
272 |
273 |
274 | def MIN(self):
275 | pass
276 |
--------------------------------------------------------------------------------
/customize/customize.py:
--------------------------------------------------------------------------------
1 | from indicator import interface
2 | import numpy as np
3 |
4 |
5 | class Customize:
6 | """
7 | 自定义方法类
8 | """
9 | def __init__(self):
10 | pass
11 |
12 | def method(self):
13 | pass
14 |
--------------------------------------------------------------------------------
/examples/atr_strategy.py:
--------------------------------------------------------------------------------
1 | """
2 | 简单atr策略 atr = info.atr()
3 | """
4 |
5 | import json
6 | from datetime import datetime, date
7 | from ctpbee import LooperApi, Vessel
8 | from ctpbee.constant import Direction
9 | from indicator.interface import Indicator
10 |
11 |
12 | def get_data(start, end, symbol, exchange, level):
13 | """ using rqdatac to make an example """
14 | # import rqdatac as rq
15 | # from rqdatac import get_price, id_convert
16 | # username = "license"
17 | # password = "NK-Ci7vnLsRiPPWYwxvvPYdYM90vxN60qUB5tVac2mQuvZ8f9Mq8K_nnUqVspOpi4BLTkSLgq8OQFpOOj7L" \
18 | # "t7AbdBZEBqRK74fIJH5vsaAfFQgl-tuB8l03axrW8cyN6-nBUho_6Y5VCRI63Mx_PN54nsQOpc1psIGEz" \
19 | # "gND8c6Y=bqMVlABkpSlrDNk4DgG-1QXNknJtk0Kkw2axvFDa0E_XPMqOcBxifuRa_DFI2svseXU-8A" \
20 | # "eLjchnTkeuvQkKh6nrfehVDiXjoMeq5sXgqpbgFAd4A5j2B1a0gpE3cb5kXb42n13fGwFaGris" \
21 | # "8-eKzz_jncvuAamkJEQQV0aLdiw="
22 | # host = "rqdatad-pro.ricequant.com"
23 | # port = 16011
24 | # rq.init(username, password, (host, port))
25 | # symbol_rq = id_convert(symbol)
26 | # data = get_price(symbol_rq, start_date=start, end_date=end, frequency=level, fields=None,
27 | # adjust_type='pre', skip_suspended=False, market='cn', expect_df=False)
28 | # origin = data.to_dict(orient='records')
29 | # result = []
30 | # for x in origin:
31 | # do = {}
32 | # do['open_price'] = x['open']
33 | # do['low_price'] = x['low']
34 | # do['high_price'] = x['high']
35 | # do['close_price'] = x['close']
36 | # do['datetime'] = datetime.strptime(str(x['trading_date']), "%Y-%m-%d %H:%M:%S")
37 | # do['symbol'] = symbol
38 | # do['local_symbol'] = symbol + "." + exchange
39 | # do['exchange'] = exchange
40 | # result.append(do)
41 | # return result
42 |
43 |
44 | def get_a_strategy():
45 | class SmaStrategy(LooperApi):
46 |
47 | def __init__(self, name):
48 | super().__init__(name)
49 | self.count = 1
50 | self.pos = 0
51 |
52 | self.bar_3 = Indicator() # 3分钟bar线
53 | self.bar_3.open_json('../zn1912.SHFE.json') # 读取本地数据
54 |
55 | self.allow_max_price = 5000 # 设置价格上限 当价格达到这个就卖出 防止突然跌
56 | self.allow_low_price = 2000 # 设置价格下限 当价格低出这里就卖 防止巨亏
57 |
58 | def on_bar(self, bar):
59 | # todo: 真实平均范围
60 | """ """
61 | self.bar_3.add_bar(bar)
62 | if not self.bar_3.inited:
63 | return
64 | close = self.bar_3.close
65 |
66 | atr = self.bar_3.atr()
67 |
68 | if self.allow_max_price < close[-1] and self.pos > 0:
69 | self.action.sell(bar.close_price, self.pos, bar)
70 |
71 | if self.allow_low_price > close[-1] and self.pos > 0:
72 | self.action.sell(bar.close_price, self.pos, bar)
73 |
74 | ###############
75 | # 暂时不写 #
76 | ##############
77 | pass
78 |
79 | def on_trade(self, trade):
80 | if trade.direction == Direction.LONG:
81 | self.pos += trade.volume
82 | else:
83 | self.pos -= trade.volume
84 |
85 | def init_params(self, data):
86 | """"""
87 | # print("我在设置策略参数")
88 |
89 | return SmaStrategy("double_ma")
90 |
91 |
92 | def save_data_json(data):
93 | result = {"result": data}
94 |
95 | class CJsonEncoder(json.JSONEncoder):
96 | def default(self, obj):
97 | if isinstance(obj, datetime):
98 | return obj.strftime('%Y-%m-%d %H:%M:%S')
99 | elif isinstance(obj, date):
100 | return obj.strftime('%Y-%m-%d')
101 | else:
102 | return json.JSONEncoder.default(self, obj)
103 |
104 | with open("../data.json", "w") as f:
105 | json.dump(result, f, cls=CJsonEncoder)
106 |
107 |
108 | def load_data():
109 | with open("../data.json", "r") as f:
110 | data = json.load(f)
111 | return data.get("result")
112 |
113 |
114 | def run_main(data):
115 | vessel = Vessel()
116 | vessel.add_data(data)
117 | stra = get_a_strategy()
118 | vessel.add_strategy(stra)
119 | vessel.set_params({"looper":
120 | {"initial_capital": 100000,
121 | "commission": 0.005,
122 | "deal_pattern": "price",
123 | "size_map": {"ag1912.SHFE": 15},
124 | "today_commission": 0.005,
125 | "yesterday_commission": 0.02,
126 | "close_commission": 0.005,
127 | "slippage_sell": 0,
128 | "slippage_cover": 0,
129 | "slippage_buy": 0,
130 | "slippage_short": 0,
131 | "close_pattern": "yesterday",
132 | },
133 | "strategy": {}
134 | })
135 | vessel.run()
136 | from pprint import pprint
137 | result = vessel.get_result()
138 | pprint(result)
139 |
140 |
141 | if __name__ == '__main__':
142 | data = load_data()
143 | for x in data:
144 | x['datetime'] = datetime.strptime(str(x['datetime']), "%Y-%m-%d %H:%M:%S")
145 | run_main(data)
--------------------------------------------------------------------------------
/examples/boll_strategy.py:
--------------------------------------------------------------------------------
1 | """
2 | 简单boll策略 top, middle, bottom = info.boll()
3 | """
4 |
5 | import json
6 | from datetime import datetime, date
7 | from ctpbee import LooperApi, Vessel
8 | from ctpbee.constant import Direction
9 | from indicator.interface import Indicator
10 |
11 |
12 | def get_data(start, end, symbol, exchange, level):
13 | """ using rqdatac to make an example """
14 | # import rqdatac as rq
15 | # from rqdatac import get_price, id_convert
16 | # username = "license"
17 | # password = "NK-Ci7vnLsRiPPWYwxvvPYdYM90vxN60qUB5tVac2mQuvZ8f9Mq8K_nnUqVspOpi4BLTkSLgq8OQFpOOj7L" \
18 | # "t7AbdBZEBqRK74fIJH5vsaAfFQgl-tuB8l03axrW8cyN6-nBUho_6Y5VCRI63Mx_PN54nsQOpc1psIGEz" \
19 | # "gND8c6Y=bqMVlABkpSlrDNk4DgG-1QXNknJtk0Kkw2axvFDa0E_XPMqOcBxifuRa_DFI2svseXU-8A" \
20 | # "eLjchnTkeuvQkKh6nrfehVDiXjoMeq5sXgqpbgFAd4A5j2B1a0gpE3cb5kXb42n13fGwFaGris" \
21 | # "8-eKzz_jncvuAamkJEQQV0aLdiw="
22 | # host = "rqdatad-pro.ricequant.com"
23 | # port = 16011
24 | # rq.init(username, password, (host, port))
25 | # symbol_rq = id_convert(symbol)
26 | # data = get_price(symbol_rq, start_date=start, end_date=end, frequency=level, fields=None,
27 | # adjust_type='pre', skip_suspended=False, market='cn', expect_df=False)
28 | # origin = data.to_dict(orient='records')
29 | # result = []
30 | # for x in origin:
31 | # do = {}
32 | # do['open_price'] = x['open']
33 | # do['low_price'] = x['low']
34 | # do['high_price'] = x['high']
35 | # do['close_price'] = x['close']
36 | # do['datetime'] = datetime.strptime(str(x['trading_date']), "%Y-%m-%d %H:%M:%S")
37 | # do['symbol'] = symbol
38 | # do['local_symbol'] = symbol + "." + exchange
39 | # do['exchange'] = exchange
40 | # result.append(do)
41 | # return result
42 |
43 |
44 | def get_a_strategy():
45 | class SmaStrategy(LooperApi):
46 |
47 | def __init__(self, name):
48 | super().__init__(name)
49 | self.count = 1
50 | self.pos = 0
51 |
52 | self.bar_3 = Indicator() # 3分钟bar线
53 | # self.bar_3.open_json('../zn1912.SHFE.json') # 读取本地数据
54 |
55 | self.allow_max_price = 5000 # 设置价格上限 当价格达到这个就卖出 防止突然跌
56 | self.allow_low_price = 2000 # 设置价格下限 当价格低出这里就卖 防止巨亏
57 |
58 | def on_bar(self, bar):
59 | # todo: 布林带
60 | """ """
61 | self.bar_3.add_bar(bar)
62 | if not self.bar_3.inited:
63 | return
64 | top, middle, bottom = self.bar_3.boll()
65 |
66 | if self.allow_max_price < bar.close_price and self.pos > 0:
67 | self.action.sell(bar.close_price, self.pos, bar)
68 |
69 | if self.allow_low_price > bar.close_price and self.pos > 0:
70 | self.action.sell(bar.close_price, self.pos, bar)
71 |
72 | # 均线大于中线 说明是涨
73 | if bar.close_price > middle[-1]:
74 | # 没有就买
75 | if self.pos == 0:
76 | self.action.buy(bar.close_price, 1, bar)
77 |
78 | elif self.pos < 0:
79 | self.action.cover(bar.close_price, 1, bar)
80 | self.action.buy(bar.close_price, 1, bar)
81 | # 跌
82 | elif bar.close_price <= middle[-1]:
83 | if self.pos == 0:
84 | pass
85 | elif self.pos > 0:
86 | self.action.sell(bar.close_price, 1, bar)
87 | self.action.short(bar.close_price, 1, bar)
88 |
89 | def on_trade(self, trade):
90 | if trade.direction == Direction.LONG:
91 | self.pos += trade.volume
92 | else:
93 | self.pos -= trade.volume
94 |
95 | def init_params(self, data):
96 | """"""
97 | # print("我在设置策略参数")
98 |
99 | return SmaStrategy("double_ma")
100 |
101 |
102 | def save_data_json(data):
103 | result = {"result": data}
104 |
105 | class CJsonEncoder(json.JSONEncoder):
106 | def default(self, obj):
107 | if isinstance(obj, datetime):
108 | return obj.strftime('%Y-%m-%d %H:%M:%S')
109 | elif isinstance(obj, date):
110 | return obj.strftime('%Y-%m-%d')
111 | else:
112 | return json.JSONEncoder.default(self, obj)
113 |
114 | with open("../data.json", "w") as f:
115 | json.dump(result, f, cls=CJsonEncoder)
116 |
117 |
118 | def load_data():
119 | with open("../data.json", "r") as f:
120 | data = json.load(f)
121 | return data.get("result")
122 |
123 |
124 | def run_main(data):
125 | vessel = Vessel()
126 | vessel.add_data(data)
127 | stra = get_a_strategy()
128 | vessel.add_strategy(stra)
129 | vessel.set_params({"looper":
130 | {"initial_capital": 100000,
131 | "commission": 0.005,
132 | "deal_pattern": "price",
133 | "size_map": {"ag1912.SHFE": 15},
134 | "today_commission": 0.005,
135 | "yesterday_commission": 0.02,
136 | "close_commission": 0.005,
137 | "slippage_sell": 0,
138 | "slippage_cover": 0,
139 | "slippage_buy": 0,
140 | "slippage_short": 0,
141 | "close_pattern": "yesterday",
142 | },
143 | "strategy": {}
144 | })
145 | vessel.run()
146 | from pprint import pprint
147 | result = vessel.get_result()
148 | pprint(result)
149 |
150 |
151 | if __name__ == '__main__':
152 | data = load_data()
153 | for x in data:
154 | x['datetime'] = datetime.strptime(str(x['datetime']), "%Y-%m-%d %H:%M:%S")
155 | run_main(data)
--------------------------------------------------------------------------------
/examples/cci_strategy.py:
--------------------------------------------------------------------------------
1 | """
2 | 简单收盘价策略 cci = info.cci
3 | """
4 |
5 | import json
6 | from datetime import datetime, date
7 |
8 | from ctpbee import LooperApi, Vessel
9 | from ctpbee.constant import Direction
10 | from indicator.interface import Indicator
11 |
12 |
13 | # def get_data(start, end, symbol, exchange, level):
14 | # """ using rqdatac to make an example """
15 | # import rqdatac as rq
16 | # from rqdatac import get_price, id_convert
17 | # username = "license"
18 | # password = "NK-Ci7vnLsRiPPWYwxvvPYdYM90vxN60qUB5tVac2mQuvZ8f9Mq8K_nnUqVspOpi4BLTkSLgq8OQFpOOj7L" \
19 | # "t7AbdBZEBqRK74fIJH5vsaAfFQgl-tuB8l03axrW8cyN6-nBUho_6Y5VCRI63Mx_PN54nsQOpc1psIGEz" \
20 | # "gND8c6Y=bqMVlABkpSlrDNk4DgG-1QXNknJtk0Kkw2axvFDa0E_XPMqOcBxifuRa_DFI2svseXU-8A" \
21 | # "eLjchnTkeuvQkKh6nrfehVDiXjoMeq5sXgqpbgFAd4A5j2B1a0gpE3cb5kXb42n13fGwFaGris" \
22 | # "8-eKzz_jncvuAamkJEQQV0aLdiw="
23 | # host = "rqdatad-pro.ricequant.com"
24 | # port = 16011
25 | # rq.init(username, password, (host, port))
26 | # symbol_rq = id_convert(symbol)
27 | # data = get_price(symbol_rq, start_date=start, end_date=end, frequency=level, fields=None,
28 | # adjust_type='pre', skip_suspended=False, market='cn', expect_df=False)
29 | # origin = data.to_dict(orient='records')
30 | # result = []
31 | # for x in origin:
32 | # do = {}
33 | # do['open_price'] = x['open']
34 | # do['low_price'] = x['low']
35 | # do['high_price'] = x['high']
36 | # do['close_price'] = x['close']
37 | # do['datetime'] = datetime.strptime(str(x['trading_date']), "%Y-%m-%d %H:%M:%S")
38 | # do['symbol'] = symbol
39 | # do['local_symbol'] = symbol + "." + exchange
40 | # do['exchange'] = exchange
41 | # result.append(do)
42 | # return result
43 |
44 |
45 | def get_a_strategy():
46 |
47 | class DoubleMaStrategy(LooperApi):
48 |
49 | allow_max_price = 5000 # 设置价格上限 当价格达到这个就卖出 防止突然跌 止盈
50 | allow_low_price = 2000 # 设置价格下限 当价格低出这里就卖 防止巨亏 止损
51 |
52 | def __init__(self, name):
53 | super().__init__(name)
54 | self.count = 1
55 | self.api = Indicator()
56 | self.api.open_json("../zn1912.SHFE.json")
57 | self.pos = 0
58 |
59 | def on_bar(self, bar):
60 | # todo: 均线
61 | """ """
62 | am = self.api
63 | am.add_bar(bar)
64 | if not am.inited:
65 | return
66 | cci = am.cci()
67 | pass
68 |
69 | def on_trade(self, trade):
70 | if trade.direction == Direction.LONG:
71 | self.pos += trade.volume
72 | else:
73 | self.pos -= trade.volume
74 |
75 | def init_params(self, data):
76 | """"""
77 | # print("我在设置策略参数")
78 |
79 | return DoubleMaStrategy("double_ma")
80 |
81 |
82 | def save_data_json(data):
83 | result = {"result": data}
84 |
85 | class CJsonEncoder(json.JSONEncoder):
86 | def default(self, obj):
87 | if isinstance(obj, datetime):
88 | return obj.strftime('%Y-%m-%d %H:%M:%S')
89 | elif isinstance(obj, date):
90 | return obj.strftime('%Y-%m-%d')
91 | else:
92 | return json.JSONEncoder.default(self, obj)
93 |
94 | with open("../data.json", "w") as f:
95 | json.dump(result, f, cls=CJsonEncoder)
96 |
97 |
98 | def load_data():
99 | with open("../data.json", "r") as f:
100 | data = json.load(f)
101 | return data.get("result")
102 |
103 |
104 | def run_main(data):
105 | vessel = Vessel()
106 | vessel.add_data(data)
107 | stra = get_a_strategy()
108 | vessel.add_strategy(stra)
109 | vessel.set_params({"looper":
110 | {"initial_capital": 100000,
111 | "commission": 0.005,
112 | "deal_pattern": "price",
113 | "size_map": {"ag1912.SHFE": 15},
114 | "today_commission": 0.005,
115 | "yesterday_commission": 0.02,
116 | "close_commission": 0.005,
117 | "slippage_sell": 0,
118 | "slippage_cover": 0,
119 | "slippage_buy": 0,
120 | "slippage_short": 0,
121 | "close_pattern": "yesterday",
122 | },
123 | "strategy": {}
124 | })
125 | vessel.run()
126 | from pprint import pprint
127 | result = vessel.get_result()
128 | pprint(result)
129 |
130 |
131 | if __name__ == '__main__':
132 | # data = get_data(start="2019-1-5", end="2019-9-1", symbol="ag1912", exchange="SHFE", level="15m")
133 | # save_data_json(data)
134 | data = load_data()
135 | for x in data:
136 | x['datetime'] = datetime.strptime(str(x['datetime']), "%Y-%m-%d %H:%M:%S")
137 | run_main(data)
138 |
--------------------------------------------------------------------------------
/examples/close_strategy.py:
--------------------------------------------------------------------------------
1 | """
2 | 简单收盘价策略 close = info.close
3 | """
4 |
5 | import json
6 | from datetime import datetime, date
7 |
8 | from ctpbee import LooperApi, Vessel
9 | from ctpbee.constant import Direction
10 | from indicator.interface import Indicator
11 |
12 |
13 | # def get_data(start, end, symbol, exchange, level):
14 | # """ using rqdatac to make an example """
15 | # import rqdatac as rq
16 | # from rqdatac import get_price, id_convert
17 | # username = "license"
18 | # password = "NK-Ci7vnLsRiPPWYwxvvPYdYM90vxN60qUB5tVac2mQuvZ8f9Mq8K_nnUqVspOpi4BLTkSLgq8OQFpOOj7L" \
19 | # "t7AbdBZEBqRK74fIJH5vsaAfFQgl-tuB8l03axrW8cyN6-nBUho_6Y5VCRI63Mx_PN54nsQOpc1psIGEz" \
20 | # "gND8c6Y=bqMVlABkpSlrDNk4DgG-1QXNknJtk0Kkw2axvFDa0E_XPMqOcBxifuRa_DFI2svseXU-8A" \
21 | # "eLjchnTkeuvQkKh6nrfehVDiXjoMeq5sXgqpbgFAd4A5j2B1a0gpE3cb5kXb42n13fGwFaGris" \
22 | # "8-eKzz_jncvuAamkJEQQV0aLdiw="
23 | # host = "rqdatad-pro.ricequant.com"
24 | # port = 16011
25 | # rq.init(username, password, (host, port))
26 | # symbol_rq = id_convert(symbol)
27 | # data = get_price(symbol_rq, start_date=start, end_date=end, frequency=level, fields=None,
28 | # adjust_type='pre', skip_suspended=False, market='cn', expect_df=False)
29 | # origin = data.to_dict(orient='records')
30 | # result = []
31 | # for x in origin:
32 | # do = {}
33 | # do['open_price'] = x['open']
34 | # do['low_price'] = x['low']
35 | # do['high_price'] = x['high']
36 | # do['close_price'] = x['close']
37 | # do['datetime'] = datetime.strptime(str(x['trading_date']), "%Y-%m-%d %H:%M:%S")
38 | # do['symbol'] = symbol
39 | # do['local_symbol'] = symbol + "." + exchange
40 | # do['exchange'] = exchange
41 | # result.append(do)
42 | # return result
43 |
44 |
45 | def get_a_strategy():
46 |
47 | class DoubleMaStrategy(LooperApi):
48 |
49 | allow_max_price = 5000 # 设置价格上限 当价格达到这个就卖出 防止突然跌 止盈
50 | allow_low_price = 2000 # 设置价格下限 当价格低出这里就卖 防止巨亏 止损
51 |
52 | def __init__(self, name):
53 | super().__init__(name)
54 | self.count = 1
55 | self.api = Indicator()
56 | # self.api.open_json("../zn1912.SHFE.json")
57 | self.pos = 0
58 |
59 | def on_bar(self, bar):
60 | # todo: 均线
61 | """ """
62 | am = self.api
63 | am.add_bar(bar)
64 | if not am.inited:
65 | return
66 | # 收盘
67 | close = am.close
68 | # 允许最大价格小于当前收盘价
69 | if self.allow_max_price <= close[-1] and self.pos > 0:
70 | self.action.sell(bar.close_price, self.pos, bar)
71 | # 允许最小价格大于当前收盘价
72 | if self.allow_low_price >= close[-1] and self.pos > 0:
73 | self.action.sell(bar.close_price, self.pos, bar)
74 | # 接连两天涨
75 | if close[-1] > close[-2] > close[-3]:
76 | if self.pos == 0:
77 | self.action.buy(bar.close_price, 1, bar)
78 | # 反向进行开仓
79 | elif self.pos < 0:
80 | self.action.cover(bar.close_price, 1, bar)
81 | self.action.buy(bar.close_price, 1, bar)
82 | # 接连两天降
83 | elif close[-1] < close[-2] < close[-3]:
84 | if self.pos == 0:
85 | pass
86 | # 反向进行开仓
87 | elif self.pos > 0:
88 | self.action.sell(bar.close_price, 1, bar)
89 | self.action.short(bar.close_price, 1, bar)
90 |
91 | def on_trade(self, trade):
92 | if trade.direction == Direction.LONG:
93 | self.pos += trade.volume
94 | else:
95 | self.pos -= trade.volume
96 |
97 | def init_params(self, data):
98 | """"""
99 | # print("我在设置策略参数")
100 |
101 | return DoubleMaStrategy("double_ma")
102 |
103 |
104 | def save_data_json(data):
105 | result = {"result": data}
106 |
107 | class CJsonEncoder(json.JSONEncoder):
108 | def default(self, obj):
109 | if isinstance(obj, datetime):
110 | return obj.strftime('%Y-%m-%d %H:%M:%S')
111 | elif isinstance(obj, date):
112 | return obj.strftime('%Y-%m-%d')
113 | else:
114 | return json.JSONEncoder.default(self, obj)
115 |
116 | with open("../data.json", "w") as f:
117 | json.dump(result, f, cls=CJsonEncoder)
118 |
119 |
120 | def load_data():
121 | with open("../data.json", "r") as f:
122 | data = json.load(f)
123 | return data.get("result")
124 |
125 |
126 | def run_main(data):
127 | vessel = Vessel()
128 | vessel.add_data(data)
129 | stra = get_a_strategy()
130 | vessel.add_strategy(stra)
131 | vessel.set_params({"looper":
132 | {"initial_capital": 100000,
133 | "commission": 0.005,
134 | "deal_pattern": "price",
135 | "size_map": {"ag1912.SHFE": 15},
136 | "today_commission": 0.005,
137 | "yesterday_commission": 0.02,
138 | "close_commission": 0.005,
139 | "slippage_sell": 0,
140 | "slippage_cover": 0,
141 | "slippage_buy": 0,
142 | "slippage_short": 0,
143 | "close_pattern": "yesterday",
144 | },
145 | "strategy": {}
146 | })
147 | vessel.run()
148 | from pprint import pprint
149 | result = vessel.get_result()
150 | pprint(result)
151 |
152 |
153 | if __name__ == '__main__':
154 | # data = get_data(start="2019-1-5", end="2019-9-1", symbol="ag1912", exchange="SHFE", level="15m")
155 | # save_data_json(data)
156 | data = load_data()
157 | for x in data:
158 | x['datetime'] = datetime.strptime(str(x['datetime']), "%Y-%m-%d %H:%M:%S")
159 | run_main(data)
160 |
--------------------------------------------------------------------------------
/examples/ema_strategy.py:
--------------------------------------------------------------------------------
1 | """
2 | 简单ema策略 ema = info.ema()
3 | """
4 |
5 | import json
6 | from datetime import datetime, date
7 | from ctpbee import LooperApi, Vessel
8 | from ctpbee.constant import Direction
9 | from indicator.interface import Indicator
10 |
11 |
12 | def get_data(start, end, symbol, exchange, level):
13 | """ using rqdatac to make an example """
14 | # import rqdatac as rq
15 | # from rqdatac import get_price, id_convert
16 | # username = "license"
17 | # password = "NK-Ci7vnLsRiPPWYwxvvPYdYM90vxN60qUB5tVac2mQuvZ8f9Mq8K_nnUqVspOpi4BLTkSLgq8OQFpOOj7L" \
18 | # "t7AbdBZEBqRK74fIJH5vsaAfFQgl-tuB8l03axrW8cyN6-nBUho_6Y5VCRI63Mx_PN54nsQOpc1psIGEz" \
19 | # "gND8c6Y=bqMVlABkpSlrDNk4DgG-1QXNknJtk0Kkw2axvFDa0E_XPMqOcBxifuRa_DFI2svseXU-8A" \
20 | # "eLjchnTkeuvQkKh6nrfehVDiXjoMeq5sXgqpbgFAd4A5j2B1a0gpE3cb5kXb42n13fGwFaGris" \
21 | # "8-eKzz_jncvuAamkJEQQV0aLdiw="
22 | # host = "rqdatad-pro.ricequant.com"
23 | # port = 16011
24 | # rq.init(username, password, (host, port))
25 | # symbol_rq = id_convert(symbol)
26 | # data = get_price(symbol_rq, start_date=start, end_date=end, frequency=level, fields=None,
27 | # adjust_type='pre', skip_suspended=False, market='cn', expect_df=False)
28 | # origin = data.to_dict(orient='records')
29 | # result = []
30 | # for x in origin:
31 | # do = {}
32 | # do['open_price'] = x['open']
33 | # do['low_price'] = x['low']
34 | # do['high_price'] = x['high']
35 | # do['close_price'] = x['close']
36 | # do['datetime'] = datetime.strptime(str(x['trading_date']), "%Y-%m-%d %H:%M:%S")
37 | # do['symbol'] = symbol
38 | # do['local_symbol'] = symbol + "." + exchange
39 | # do['exchange'] = exchange
40 | # result.append(do)
41 | # return result
42 |
43 |
44 | def get_a_strategy():
45 | class SmaStrategy(LooperApi):
46 |
47 | def __init__(self, name):
48 | super().__init__(name)
49 | self.count = 1
50 | self.pos = 0
51 |
52 | self.bar_3 = Indicator() # 3分钟bar线
53 | self.bar_3.open_json('../zn1912.SHFE.json') # 读取本地数据
54 |
55 | self.allow_max_price = 5000 # 设置价格上限 当价格达到这个就卖出 防止突然跌
56 | self.allow_low_price = 2000 # 设置价格下限 当价格低出这里就卖 防止巨亏
57 |
58 | def on_bar(self, bar):
59 | # todo: 移动平均线
60 | """ """
61 | self.bar_3.add_bar(bar)
62 | if not self.bar_3.inited:
63 | return
64 | ema = self.bar_3.ema()
65 |
66 | if self.allow_max_price < bar.close_price and self.pos > 0:
67 | self.action.sell(bar.close_price, self.pos, bar)
68 |
69 | if self.allow_low_price > bar.close_price and self.pos > 0:
70 | self.action.sell(bar.close_price, self.pos, bar)
71 |
72 | # 均线大于中线
73 | if ema[-1] > ema[-2] and ema[-1] < bar.close_price:
74 | # 没有就买
75 | if self.pos == 0:
76 | self.action.buy(bar.close_price, 1, bar)
77 | if self.pos < 0:
78 | self.action.cover(bar.close_price, 1, bar)
79 | self.action.buy(bar.close_price, 1, bar)
80 | # 跌
81 | elif ema[-1] < ema[-2] or ema[-1] > bar.close_price:
82 | if self.pos == 0:
83 | pass
84 | elif self.pos > 0:
85 | self.action.sell(bar.close_price, 1, bar)
86 | self.action.short(bar.close_price, 1, bar)
87 |
88 | def on_trade(self, trade):
89 | if trade.direction == Direction.LONG:
90 | self.pos += trade.volume
91 | else:
92 | self.pos -= trade.volume
93 |
94 | def init_params(self, data):
95 | """"""
96 | # print("我在设置策略参数")
97 |
98 | return SmaStrategy("double_ma")
99 |
100 |
101 | def save_data_json(data):
102 | result = {"result": data}
103 |
104 | class CJsonEncoder(json.JSONEncoder):
105 | def default(self, obj):
106 | if isinstance(obj, datetime):
107 | return obj.strftime('%Y-%m-%d %H:%M:%S')
108 | elif isinstance(obj, date):
109 | return obj.strftime('%Y-%m-%d')
110 | else:
111 | return json.JSONEncoder.default(self, obj)
112 |
113 | with open("../data.json", "w") as f:
114 | json.dump(result, f, cls=CJsonEncoder)
115 |
116 |
117 | def load_data():
118 | with open("../data.json", "r") as f:
119 | data = json.load(f)
120 | return data.get("result")
121 |
122 |
123 | def run_main(data):
124 | vessel = Vessel()
125 | vessel.add_data(data)
126 | stra = get_a_strategy()
127 | vessel.add_strategy(stra)
128 | vessel.set_params({"looper":
129 | {"initial_capital": 100000,
130 | "commission": 0.005,
131 | "deal_pattern": "price",
132 | "size_map": {"ag1912.SHFE": 15},
133 | "today_commission": 0.005,
134 | "yesterday_commission": 0.02,
135 | "close_commission": 0.005,
136 | "slippage_sell": 0,
137 | "slippage_cover": 0,
138 | "slippage_buy": 0,
139 | "slippage_short": 0,
140 | "close_pattern": "yesterday",
141 | },
142 | "strategy": {}
143 | })
144 | vessel.run()
145 | from pprint import pprint
146 | result = vessel.get_result()
147 | pprint(result)
148 |
149 |
150 | if __name__ == '__main__':
151 | data = load_data()
152 | for x in data:
153 | x['datetime'] = datetime.strptime(str(x['datetime']), "%Y-%m-%d %H:%M:%S")
154 | run_main(data)
--------------------------------------------------------------------------------
/examples/kd_strategy.py:
--------------------------------------------------------------------------------
1 | """
2 | 简单kd策略 k, d = info.kd() # kdj(j=3d-2k)
3 | """
4 |
5 | import json
6 | from datetime import datetime, date
7 | from ctpbee import LooperApi, Vessel
8 | from ctpbee.constant import Direction
9 | from indicator.interface import Indicator
10 |
11 |
12 | def get_data(start, end, symbol, exchange, level):
13 | """ using rqdatac to make an example """
14 | # import rqdatac as rq
15 | # from rqdatac import get_price, id_convert
16 | # username = "license"
17 | # password = "NK-Ci7vnLsRiPPWYwxvvPYdYM90vxN60qUB5tVac2mQuvZ8f9Mq8K_nnUqVspOpi4BLTkSLgq8OQFpOOj7L" \
18 | # "t7AbdBZEBqRK74fIJH5vsaAfFQgl-tuB8l03axrW8cyN6-nBUho_6Y5VCRI63Mx_PN54nsQOpc1psIGEz" \
19 | # "gND8c6Y=bqMVlABkpSlrDNk4DgG-1QXNknJtk0Kkw2axvFDa0E_XPMqOcBxifuRa_DFI2svseXU-8A" \
20 | # "eLjchnTkeuvQkKh6nrfehVDiXjoMeq5sXgqpbgFAd4A5j2B1a0gpE3cb5kXb42n13fGwFaGris" \
21 | # "8-eKzz_jncvuAamkJEQQV0aLdiw="
22 | # host = "rqdatad-pro.ricequant.com"
23 | # port = 16011
24 | # rq.init(username, password, (host, port))
25 | # symbol_rq = id_convert(symbol)
26 | # data = get_price(symbol_rq, start_date=start, end_date=end, frequency=level, fields=None,
27 | # adjust_type='pre', skip_suspended=False, market='cn', expect_df=False)
28 | # origin = data.to_dict(orient='records')
29 | # result = []
30 | # for x in origin:
31 | # do = {}
32 | # do['open_price'] = x['open']
33 | # do['low_price'] = x['low']
34 | # do['high_price'] = x['high']
35 | # do['close_price'] = x['close']
36 | # do['datetime'] = datetime.strptime(str(x['trading_date']), "%Y-%m-%d %H:%M:%S")
37 | # do['symbol'] = symbol
38 | # do['local_symbol'] = symbol + "." + exchange
39 | # do['exchange'] = exchange
40 | # result.append(do)
41 | # return result
42 |
43 |
44 | def get_a_strategy():
45 | class SmaStrategy(LooperApi):
46 |
47 | def __init__(self, name):
48 | super().__init__(name)
49 | self.count = 1
50 | self.pos = 0
51 |
52 | self.bar_3 = Indicator() # 3分钟bar线
53 | self.bar_3.open_json('../zn1912.SHFE.json') # 读取本地数据
54 |
55 | self.allow_max_price = 5000 # 设置价格上限 当价格达到这个就卖出 防止突然跌
56 | self.allow_low_price = 2000 # 设置价格下限 当价格低出这里就卖 防止巨亏
57 |
58 | def on_bar(self, bar):
59 | # todo: 随机指标
60 | """ """
61 | self.bar_3.add_bar(bar)
62 | if not self.bar_3.inited:
63 | return
64 | close = self.bar_3.close
65 | k, d = self.bar_3.kd()
66 |
67 | if self.allow_max_price < close[-1] and self.pos > 0:
68 | self.action.sell(bar.close_price, self.pos, bar)
69 |
70 | if self.allow_low_price > close[-1] and self.pos > 0:
71 | self.action.sell(bar.close_price, self.pos, bar)
72 |
73 | # 金叉
74 | if k[-2] > d[-2] and k[-1] == d[-1]:
75 | # 没有就买
76 | if self.pos == 0:
77 | self.action.buy(bar.close_price, 1, bar)
78 | # 死叉
79 | if k[-2] == d[-2] and k[-1] < d[-1]:
80 | if self.pos > 0:
81 | self.action.sell(bar.close_price, 1, bar)
82 |
83 | def on_trade(self, trade):
84 | if trade.direction == Direction.LONG:
85 | self.pos += trade.volume
86 | else:
87 | self.pos -= trade.volume
88 |
89 | def init_params(self, data):
90 | """"""
91 | # print("我在设置策略参数")
92 |
93 | return SmaStrategy("double_ma")
94 |
95 |
96 | def save_data_json(data):
97 | result = {"result": data}
98 |
99 | class CJsonEncoder(json.JSONEncoder):
100 | def default(self, obj):
101 | if isinstance(obj, datetime):
102 | return obj.strftime('%Y-%m-%d %H:%M:%S')
103 | elif isinstance(obj, date):
104 | return obj.strftime('%Y-%m-%d')
105 | else:
106 | return json.JSONEncoder.default(self, obj)
107 |
108 | with open("../data.json", "w") as f:
109 | json.dump(result, f, cls=CJsonEncoder)
110 |
111 |
112 | def load_data():
113 | with open("../data.json", "r") as f:
114 | data = json.load(f)
115 | return data.get("result")
116 |
117 |
118 | def run_main(data):
119 | vessel = Vessel()
120 | vessel.add_data(data)
121 | stra = get_a_strategy()
122 | vessel.add_strategy(stra)
123 | vessel.set_params({"looper":
124 | {"initial_capital": 100000,
125 | "commission": 0.005,
126 | "deal_pattern": "price",
127 | "size_map": {"ag1912.SHFE": 15},
128 | "today_commission": 0.005,
129 | "yesterday_commission": 0.02,
130 | "close_commission": 0.005,
131 | "slippage_sell": 0,
132 | "slippage_cover": 0,
133 | "slippage_buy": 0,
134 | "slippage_short": 0,
135 | "close_pattern": "yesterday",
136 | },
137 | "strategy": {}
138 | })
139 | vessel.run()
140 | from pprint import pprint
141 | result = vessel.get_result()
142 | pprint(result)
143 |
144 |
145 | if __name__ == '__main__':
146 | data = load_data()
147 | for x in data:
148 | x['datetime'] = datetime.strptime(str(x['datetime']), "%Y-%m-%d %H:%M:%S")
149 | run_main(data)
--------------------------------------------------------------------------------
/examples/looper_example.py:
--------------------------------------------------------------------------------
1 | """
2 | 当前回测示例
3 | 1.当前数据基于rq进行下载的
4 | 2.首先你需要调用get_data 来获得rq的数据 ,然后save_to_json保存到 json文件中去,主要在此过程中你需要手动对数据加入symbol等
5 | 3.然后通过load_data函数重复调用数据
6 | 4.调用run_main进行回测
7 |
8 | 当前的strategy是借助vnpy的 ArrayManager . 你需要对此实现一些额外的安装操作
9 |
10 | 需要额外安装的包
11 | ta-lib, rqdatac( 后面需要被取代 ?? Maybe use quantdata )
12 |
13 | 目前暂时不够完善 ---> hope it will be a very fancy framework
14 |
15 | written by somewheve 2019-9-30 08:43
16 |
17 | """
18 |
19 | import json
20 | from datetime import datetime, date
21 |
22 | from ctpbee import LooperApi, Vessel
23 | from ctpbee.constant import Direction
24 | from indicator.interface import Indicator
25 |
26 |
27 | # def get_data(start, end, symbol, exchange, level):
28 | # """ using rqdatac to make an example """
29 | # import rqdatac as rq
30 | # from rqdatac import get_price, id_convert
31 | # username = "license"
32 | # password = "NK-Ci7vnLsRiPPWYwxvvPYdYM90vxN60qUB5tVac2mQuvZ8f9Mq8K_nnUqVspOpi4BLTkSLgq8OQFpOOj7L" \
33 | # "t7AbdBZEBqRK74fIJH5vsaAfFQgl-tuB8l03axrW8cyN6-nBUho_6Y5VCRI63Mx_PN54nsQOpc1psIGEz" \
34 | # "gND8c6Y=bqMVlABkpSlrDNk4DgG-1QXNknJtk0Kkw2axvFDa0E_XPMqOcBxifuRa_DFI2svseXU-8A" \
35 | # "eLjchnTkeuvQkKh6nrfehVDiXjoMeq5sXgqpbgFAd4A5j2B1a0gpE3cb5kXb42n13fGwFaGris" \
36 | # "8-eKzz_jncvuAamkJEQQV0aLdiw="
37 | # host = "rqdatad-pro.ricequant.com"
38 | # port = 16011
39 | # rq.init(username, password, (host, port))
40 | # symbol_rq = id_convert(symbol)
41 | # data = get_price(symbol_rq, start_date=start, end_date=end, frequency=level, fields=None,
42 | # adjust_type='pre', skip_suspended=False, market='cn', expect_df=False)
43 | # origin = data.to_dict(orient='records')
44 | # result = []
45 | # for x in origin:
46 | # do = {}
47 | # do['open_price'] = x['open']
48 | # do['low_price'] = x['low']
49 | # do['high_price'] = x['high']
50 | # do['close_price'] = x['close']
51 | # do['datetime'] = datetime.strptime(str(x['trading_date']), "%Y-%m-%d %H:%M:%S")
52 | # do['symbol'] = symbol
53 | # do['local_symbol'] = symbol + "." + exchange
54 | # do['exchange'] = exchange
55 | # result.append(do)
56 | # return result
57 |
58 |
59 | def get_a_strategy():
60 |
61 | class DoubleMaStrategy(LooperApi):
62 |
63 | allow_max_price = 5000 # 设置价格上限 当价格达到这个就卖出 防止突然跌 止盈
64 | allow_low_price = 2000 # 设置价格下限 当价格低出这里就卖 防止巨亏 止损
65 |
66 | def __init__(self, name):
67 | super().__init__(name)
68 | self.count = 1
69 | self.api = Indicator()
70 | self.api.open_json("../zn1912.SHFE.json")
71 | self.pos = 0
72 |
73 | def on_bar(self, bar):
74 | # todo: 均线 和 MACD 和 BOLL 结合使用
75 | """ """
76 | am = self.api
77 | am.add_bar(bar)
78 | # 收盘
79 | close = am.close
80 | # 压力 平均 支撑
81 | # top, middle, bottom = am.boll()
82 | # DIF DEA DIF-DEA
83 | macd, signal, histo = am.macd()
84 |
85 | if self.allow_max_price <= close[-1] and self.pos > 0:
86 | self.action.sell(bar.close_price, self.pos, bar)
87 |
88 | if self.allow_low_price >= close[-1] and self.pos > 0:
89 | self.action.sell(bar.close_price, self.pos, bar)
90 | # 金叉做多 和 均线>平均
91 | if histo[-1] > 0:
92 | if self.pos == 0:
93 | self.action.buy(bar.close_price, 1, bar)
94 | elif self.pos < 0:
95 | self.action.cover(bar.close_price, 1, bar)
96 | self.action.buy(bar.close_price, 1, bar)
97 | # 死叉做空
98 | elif histo[-1] < 0:
99 | if self.pos == 0:
100 | self.action.sell(bar.close_price, 1, bar)
101 | # 反向进行开仓
102 | elif self.pos > 0:
103 | self.action.sell(bar.close_price, 1, bar)
104 | self.action.short(bar.close_price, 1, bar)
105 |
106 | def on_trade(self, trade):
107 | if trade.direction == Direction.LONG:
108 | self.pos += trade.volume
109 | else:
110 | self.pos -= trade.volume
111 |
112 | def init_params(self, data):
113 | """"""
114 | # print("我在设置策略参数")
115 |
116 | return DoubleMaStrategy("double_ma")
117 |
118 |
119 | def save_data_json(data):
120 | result = {"result": data}
121 |
122 | class CJsonEncoder(json.JSONEncoder):
123 | def default(self, obj):
124 | if isinstance(obj, datetime):
125 | return obj.strftime('%Y-%m-%d %H:%M:%S')
126 | elif isinstance(obj, date):
127 | return obj.strftime('%Y-%m-%d')
128 | else:
129 | return json.JSONEncoder.default(self, obj)
130 |
131 | with open("data.json", "w") as f:
132 | json.dump(result, f, cls=CJsonEncoder)
133 |
134 |
135 | def load_data():
136 | with open("data.json", "r") as f:
137 | data = json.load(f)
138 | return data.get("result")
139 |
140 |
141 | def run_main(data):
142 | vessel = Vessel()
143 | vessel.add_data(data)
144 | stra = get_a_strategy()
145 | vessel.add_strategy(stra)
146 | vessel.set_params({"looper":
147 | {"initial_capital": 100000,
148 | "commission": 0.005,
149 | "deal_pattern": "price",
150 | "size_map": {"ag1912.SHFE": 15},
151 | "today_commission": 0.005,
152 | "yesterday_commission": 0.02,
153 | "close_commission": 0.005,
154 | "slippage_sell": 0,
155 | "slippage_cover": 0,
156 | "slippage_buy": 0,
157 | "slippage_short": 0,
158 | "close_pattern": "yesterday",
159 | },
160 | "strategy": {}
161 | })
162 | vessel.run()
163 | from pprint import pprint
164 | result = vessel.get_result()
165 | pprint(result)
166 |
167 |
168 | if __name__ == '__main__':
169 | # data = get_data(start="2019-1-5", end="2019-9-1", symbol="ag1912", exchange="SHFE", level="15m")
170 | # save_data_json(data)
171 | data = load_data()
172 | for x in data:
173 | x['datetime'] = datetime.strptime(str(x['datetime']), "%Y-%m-%d %H:%M:%S")
174 | run_main(data)
175 |
--------------------------------------------------------------------------------
/examples/macd_strategy.py:
--------------------------------------------------------------------------------
1 | """
2 | 简单macd策略 macd, signal, histo = info.macd()
3 | """
4 |
5 | import json
6 | from datetime import datetime, date
7 | from ctpbee import LooperApi, Vessel
8 | from ctpbee.constant import Direction
9 | from indicator.interface import Indicator
10 |
11 |
12 | def get_data(start, end, symbol, exchange, level):
13 | """ using rqdatac to make an example """
14 | # import rqdatac as rq
15 | # from rqdatac import get_price, id_convert
16 | # username = "license"
17 | # password = "NK-Ci7vnLsRiPPWYwxvvPYdYM90vxN60qUB5tVac2mQuvZ8f9Mq8K_nnUqVspOpi4BLTkSLgq8OQFpOOj7L" \
18 | # "t7AbdBZEBqRK74fIJH5vsaAfFQgl-tuB8l03axrW8cyN6-nBUho_6Y5VCRI63Mx_PN54nsQOpc1psIGEz" \
19 | # "gND8c6Y=bqMVlABkpSlrDNk4DgG-1QXNknJtk0Kkw2axvFDa0E_XPMqOcBxifuRa_DFI2svseXU-8A" \
20 | # "eLjchnTkeuvQkKh6nrfehVDiXjoMeq5sXgqpbgFAd4A5j2B1a0gpE3cb5kXb42n13fGwFaGris" \
21 | # "8-eKzz_jncvuAamkJEQQV0aLdiw="
22 | # host = "rqdatad-pro.ricequant.com"
23 | # port = 16011
24 | # rq.init(username, password, (host, port))
25 | # symbol_rq = id_convert(symbol)
26 | # data = get_price(symbol_rq, start_date=start, end_date=end, frequency=level, fields=None,
27 | # adjust_type='pre', skip_suspended=False, market='cn', expect_df=False)
28 | # origin = data.to_dict(orient='records')
29 | # result = []
30 | # for x in origin:
31 | # do = {}
32 | # do['open_price'] = x['open']
33 | # do['low_price'] = x['low']
34 | # do['high_price'] = x['high']
35 | # do['close_price'] = x['close']
36 | # do['datetime'] = datetime.strptime(str(x['trading_date']), "%Y-%m-%d %H:%M:%S")
37 | # do['symbol'] = symbol
38 | # do['local_symbol'] = symbol + "." + exchange
39 | # do['exchange'] = exchange
40 | # result.append(do)
41 | # return result
42 |
43 |
44 | def get_a_strategy():
45 | class SmaStrategy(LooperApi):
46 |
47 | def __init__(self, name):
48 | super().__init__(name)
49 | self.count = 1
50 | self.pos = 0
51 |
52 | self.bar_3 = Indicator() # 3分钟bar线
53 | self.bar_3.open_json('../zn1912.SHFE.json') # 读取本地数据
54 |
55 | self.allow_max_price = 5000 # 设置价格上限 当价格达到这个就卖出 防止突然跌
56 | self.allow_low_price = 2000 # 设置价格下限 当价格低出这里就卖 防止巨亏
57 |
58 | def on_bar(self, bar):
59 | # todo: MACD
60 | """ """
61 | self.bar_3.add_bar(bar)
62 | if not self.bar_3.inited:
63 | return
64 | macd, signal, histo = self.bar_3.macd()
65 |
66 | if self.allow_max_price < bar.close_price and self.pos > 0:
67 | self.action.sell(bar.close_price, self.pos, bar)
68 |
69 | if self.allow_low_price > bar.close_price and self.pos > 0:
70 | self.action.sell(bar.close_price, self.pos, bar)
71 |
72 | # 接连三天涨
73 | if histo[-1] > 0:
74 | # 没有就买
75 | if self.pos == 0:
76 | self.action.buy(bar.close_price, 1, bar)
77 | elif self.pos < 0:
78 | self.action.cover(bar.close_price, 1, bar)
79 | self.action.buy(bar.close_price, 1, bar)
80 | else:
81 | if self.pos > 0:
82 | self.action.sell(bar.close_price, 1, bar)
83 | self.action.short(bar.close_price, 1, bar)
84 |
85 | def on_trade(self, trade):
86 | if trade.direction == Direction.LONG:
87 | self.pos += trade.volume
88 | else:
89 | self.pos -= trade.volume
90 |
91 | def init_params(self, data):
92 | """"""
93 | # print("我在设置策略参数")
94 |
95 | return SmaStrategy("double_ma")
96 |
97 |
98 | def save_data_json(data):
99 | result = {"result": data}
100 |
101 | class CJsonEncoder(json.JSONEncoder):
102 | def default(self, obj):
103 | if isinstance(obj, datetime):
104 | return obj.strftime('%Y-%m-%d %H:%M:%S')
105 | elif isinstance(obj, date):
106 | return obj.strftime('%Y-%m-%d')
107 | else:
108 | return json.JSONEncoder.default(self, obj)
109 |
110 | with open("../data.json", "w") as f:
111 | json.dump(result, f, cls=CJsonEncoder)
112 |
113 |
114 | def load_data():
115 | with open("../data.json", "r") as f:
116 | data = json.load(f)
117 | return data.get("result")
118 |
119 |
120 | def run_main(data):
121 | vessel = Vessel()
122 | vessel.add_data(data)
123 | stra = get_a_strategy()
124 | vessel.add_strategy(stra)
125 | vessel.set_params({"looper":
126 | {"initial_capital": 100000,
127 | "commission": 0.005,
128 | "deal_pattern": "price",
129 | "size_map": {"ag1912.SHFE": 15},
130 | "today_commission": 0.005,
131 | "yesterday_commission": 0.02,
132 | "close_commission": 0.005,
133 | "slippage_sell": 0,
134 | "slippage_cover": 0,
135 | "slippage_buy": 0,
136 | "slippage_short": 0,
137 | "close_pattern": "yesterday",
138 | },
139 | "strategy": {}
140 | })
141 | vessel.run()
142 | from pprint import pprint
143 | result = vessel.get_result()
144 | pprint(result)
145 |
146 |
147 | if __name__ == '__main__':
148 | data = load_data()
149 | for x in data:
150 | x['datetime'] = datetime.strptime(str(x['datetime']), "%Y-%m-%d %H:%M:%S")
151 | run_main(data)
--------------------------------------------------------------------------------
/examples/mtm_strategy.py:
--------------------------------------------------------------------------------
1 | """
2 | 简单mtm策略 mtm = info.mtm()
3 | """
4 |
5 | import json
6 | from datetime import datetime, date
7 | from ctpbee import LooperApi, Vessel
8 | from ctpbee.constant import Direction
9 | from indicator.interface import Indicator
10 |
11 |
12 | def get_data(start, end, symbol, exchange, level):
13 | """ using rqdatac to make an example """
14 | # import rqdatac as rq
15 | # from rqdatac import get_price, id_convert
16 | # username = "license"
17 | # password = "NK-Ci7vnLsRiPPWYwxvvPYdYM90vxN60qUB5tVac2mQuvZ8f9Mq8K_nnUqVspOpi4BLTkSLgq8OQFpOOj7L" \
18 | # "t7AbdBZEBqRK74fIJH5vsaAfFQgl-tuB8l03axrW8cyN6-nBUho_6Y5VCRI63Mx_PN54nsQOpc1psIGEz" \
19 | # "gND8c6Y=bqMVlABkpSlrDNk4DgG-1QXNknJtk0Kkw2axvFDa0E_XPMqOcBxifuRa_DFI2svseXU-8A" \
20 | # "eLjchnTkeuvQkKh6nrfehVDiXjoMeq5sXgqpbgFAd4A5j2B1a0gpE3cb5kXb42n13fGwFaGris" \
21 | # "8-eKzz_jncvuAamkJEQQV0aLdiw="
22 | # host = "rqdatad-pro.ricequant.com"
23 | # port = 16011
24 | # rq.init(username, password, (host, port))
25 | # symbol_rq = id_convert(symbol)
26 | # data = get_price(symbol_rq, start_date=start, end_date=end, frequency=level, fields=None,
27 | # adjust_type='pre', skip_suspended=False, market='cn', expect_df=False)
28 | # origin = data.to_dict(orient='records')
29 | # result = []
30 | # for x in origin:
31 | # do = {}
32 | # do['open_price'] = x['open']
33 | # do['low_price'] = x['low']
34 | # do['high_price'] = x['high']
35 | # do['close_price'] = x['close']
36 | # do['datetime'] = datetime.strptime(str(x['trading_date']), "%Y-%m-%d %H:%M:%S")
37 | # do['symbol'] = symbol
38 | # do['local_symbol'] = symbol + "." + exchange
39 | # do['exchange'] = exchange
40 | # result.append(do)
41 | # return result
42 |
43 |
44 | def get_a_strategy():
45 | class SmaStrategy(LooperApi):
46 |
47 | def __init__(self, name):
48 | super().__init__(name)
49 | self.count = 1
50 | self.pos = 0
51 |
52 | self.bar_3 = Indicator() # 3分钟bar线
53 | self.bar_3.open_json('../zn1912.SHFE.json') # 读取本地数据
54 |
55 | self.allow_max_price = 5000 # 设置价格上限 当价格达到这个就卖出 防止突然跌
56 | self.allow_low_price = 2000 # 设置价格下限 当价格低出这里就卖 防止巨亏
57 |
58 | def on_bar(self, bar):
59 | # todo: 动量指标
60 | """ """
61 | self.bar_3.add_bar(bar)
62 | if not self.bar_3.inited:
63 | return
64 | mtm = self.bar_3.mtm()
65 |
66 | if self.allow_max_price < bar.close_price and self.pos > 0:
67 | self.action.sell(bar.close_price, self.pos, bar)
68 |
69 | if self.allow_low_price > bar.close_price and self.pos > 0:
70 | self.action.sell(bar.close_price, self.pos, bar)
71 |
72 | # 趋势好 可能会涨 多头
73 | if mtm[-1] > 0 and mtm[-1] > mtm[-2]:
74 | # 没有就买
75 | if self.pos == 0:
76 | self.action.buy(bar.close_price, 1, bar)
77 | elif self.pos < 0:
78 | self.action.cover(bar.close_price, 1, bar)
79 | self.action.buy(bar.close_price, 1, bar)
80 | # 空头
81 | else:
82 | if self.pos > 0:
83 | self.action.sell(bar.close_price, 1, bar)
84 | self.action.short(bar.close_price, 1, bar)
85 |
86 | def on_trade(self, trade):
87 | if trade.direction == Direction.LONG:
88 | self.pos += trade.volume
89 | else:
90 | self.pos -= trade.volume
91 |
92 | def init_params(self, data):
93 | """"""
94 | # print("我在设置策略参数")
95 |
96 | return SmaStrategy("double_ma")
97 |
98 |
99 | def save_data_json(data):
100 | result = {"result": data}
101 |
102 | class CJsonEncoder(json.JSONEncoder):
103 | def default(self, obj):
104 | if isinstance(obj, datetime):
105 | return obj.strftime('%Y-%m-%d %H:%M:%S')
106 | elif isinstance(obj, date):
107 | return obj.strftime('%Y-%m-%d')
108 | else:
109 | return json.JSONEncoder.default(self, obj)
110 |
111 | with open("../data.json", "w") as f:
112 | json.dump(result, f, cls=CJsonEncoder)
113 |
114 |
115 | def load_data():
116 | with open("../data.json", "r") as f:
117 | data = json.load(f)
118 | return data.get("result")
119 |
120 |
121 | def run_main(data):
122 | vessel = Vessel()
123 | vessel.add_data(data)
124 | stra = get_a_strategy()
125 | vessel.add_strategy(stra)
126 | vessel.set_params({"looper":
127 | {"initial_capital": 100000,
128 | "commission": 0.005,
129 | "deal_pattern": "price",
130 | "size_map": {"ag1912.SHFE": 15},
131 | "today_commission": 0.005,
132 | "yesterday_commission": 0.02,
133 | "close_commission": 0.005,
134 | "slippage_sell": 0,
135 | "slippage_cover": 0,
136 | "slippage_buy": 0,
137 | "slippage_short": 0,
138 | "close_pattern": "yesterday",
139 | },
140 | "strategy": {}
141 | })
142 | vessel.run()
143 | from pprint import pprint
144 | result = vessel.get_result()
145 | pprint(result)
146 |
147 |
148 | if __name__ == '__main__':
149 | data = load_data()
150 | for x in data:
151 | x['datetime'] = datetime.strptime(str(x['datetime']), "%Y-%m-%d %H:%M:%S")
152 | run_main(data)
--------------------------------------------------------------------------------
/examples/roc_strategy.py:
--------------------------------------------------------------------------------
1 | """
2 | 简单roc策略 roc = info.roc()
3 | """
4 |
5 | import json
6 | from datetime import datetime, date
7 | from ctpbee import LooperApi, Vessel
8 | from ctpbee.constant import Direction
9 | from indicator.interface import Indicator
10 |
11 |
12 | def get_data(start, end, symbol, exchange, level):
13 | """ using rqdatac to make an example """
14 | # import rqdatac as rq
15 | # from rqdatac import get_price, id_convert
16 | # username = "license"
17 | # password = "NK-Ci7vnLsRiPPWYwxvvPYdYM90vxN60qUB5tVac2mQuvZ8f9Mq8K_nnUqVspOpi4BLTkSLgq8OQFpOOj7L" \
18 | # "t7AbdBZEBqRK74fIJH5vsaAfFQgl-tuB8l03axrW8cyN6-nBUho_6Y5VCRI63Mx_PN54nsQOpc1psIGEz" \
19 | # "gND8c6Y=bqMVlABkpSlrDNk4DgG-1QXNknJtk0Kkw2axvFDa0E_XPMqOcBxifuRa_DFI2svseXU-8A" \
20 | # "eLjchnTkeuvQkKh6nrfehVDiXjoMeq5sXgqpbgFAd4A5j2B1a0gpE3cb5kXb42n13fGwFaGris" \
21 | # "8-eKzz_jncvuAamkJEQQV0aLdiw="
22 | # host = "rqdatad-pro.ricequant.com"
23 | # port = 16011
24 | # rq.init(username, password, (host, port))
25 | # symbol_rq = id_convert(symbol)
26 | # data = get_price(symbol_rq, start_date=start, end_date=end, frequency=level, fields=None,
27 | # adjust_type='pre', skip_suspended=False, market='cn', expect_df=False)
28 | # origin = data.to_dict(orient='records')
29 | # result = []
30 | # for x in origin:
31 | # do = {}
32 | # do['open_price'] = x['open']
33 | # do['low_price'] = x['low']
34 | # do['high_price'] = x['high']
35 | # do['close_price'] = x['close']
36 | # do['datetime'] = datetime.strptime(str(x['trading_date']), "%Y-%m-%d %H:%M:%S")
37 | # do['symbol'] = symbol
38 | # do['local_symbol'] = symbol + "." + exchange
39 | # do['exchange'] = exchange
40 | # result.append(do)
41 | # return result
42 |
43 |
44 | def get_a_strategy():
45 | class SmaStrategy(LooperApi):
46 |
47 | def __init__(self, name):
48 | super().__init__(name)
49 | self.count = 1
50 | self.pos = 0
51 |
52 | self.bar_3 = Indicator() # 3分钟bar线
53 | self.bar_3.open_json('../zn1912.SHFE.json') # 读取本地数据
54 |
55 | self.allow_max_price = 5000 # 设置价格上限 当价格达到这个就卖出 防止突然跌
56 | self.allow_low_price = 2000 # 设置价格下限 当价格低出这里就卖 防止巨亏
57 |
58 | def on_bar(self, bar):
59 | # todo: ROC
60 | """ """
61 | self.bar_3.add_bar(bar)
62 | if not self.bar_3.inited:
63 | return
64 | roc = self.bar_3.roc()
65 |
66 | if self.allow_max_price < bar.close_price and self.pos > 0:
67 | self.action.sell(bar.close_price, self.pos, bar)
68 |
69 | if self.allow_low_price > bar.close_price and self.pos > 0:
70 | self.action.sell(bar.close_price, self.pos, bar)
71 |
72 | # roc大于0会涨
73 | if roc[-1] > 0:
74 | # 没有就买
75 | if self.pos == 0:
76 | self.action.buy(bar.close_price, 1, bar)
77 | elif self.pos < 0:
78 | self.action.cover(bar.close_price, 1, bar)
79 | self.action.buy(bar.close_price, 1, bar)
80 | else:
81 | if self.pos > 0:
82 | self.action.sell(bar.close_price, 1, bar)
83 | self.action.short(bar.close_price, 1, bar)
84 |
85 | def on_trade(self, trade):
86 | if trade.direction == Direction.LONG:
87 | self.pos += trade.volume
88 | else:
89 | self.pos -= trade.volume
90 |
91 | def init_params(self, data):
92 | """"""
93 | # print("我在设置策略参数")
94 |
95 | return SmaStrategy("double_ma")
96 |
97 |
98 | def save_data_json(data):
99 | result = {"result": data}
100 |
101 | class CJsonEncoder(json.JSONEncoder):
102 | def default(self, obj):
103 | if isinstance(obj, datetime):
104 | return obj.strftime('%Y-%m-%d %H:%M:%S')
105 | elif isinstance(obj, date):
106 | return obj.strftime('%Y-%m-%d')
107 | else:
108 | return json.JSONEncoder.default(self, obj)
109 |
110 | with open("../data.json", "w") as f:
111 | json.dump(result, f, cls=CJsonEncoder)
112 |
113 |
114 | def load_data():
115 | with open("../data.json", "r") as f:
116 | data = json.load(f)
117 | return data.get("result")
118 |
119 |
120 | def run_main(data):
121 | vessel = Vessel()
122 | vessel.add_data(data)
123 | stra = get_a_strategy()
124 | vessel.add_strategy(stra)
125 | vessel.set_params({"looper":
126 | {"initial_capital": 100000,
127 | "commission": 0.005,
128 | "deal_pattern": "price",
129 | "size_map": {"ag1912.SHFE": 15},
130 | "today_commission": 0.005,
131 | "yesterday_commission": 0.02,
132 | "close_commission": 0.005,
133 | "slippage_sell": 0,
134 | "slippage_cover": 0,
135 | "slippage_buy": 0,
136 | "slippage_short": 0,
137 | "close_pattern": "yesterday",
138 | },
139 | "strategy": {}
140 | })
141 | vessel.run()
142 | from pprint import pprint
143 | result = vessel.get_result()
144 | pprint(result)
145 |
146 |
147 | if __name__ == '__main__':
148 | data = load_data()
149 | for x in data:
150 | x['datetime'] = datetime.strptime(str(x['datetime']), "%Y-%m-%d %H:%M:%S")
151 | run_main(data)
--------------------------------------------------------------------------------
/examples/rsi_strategy.py:
--------------------------------------------------------------------------------
1 | """
2 | 简单相对强度指数rsi策略 rsi = info.rsi()
3 | """
4 |
5 | import json
6 | from datetime import datetime, date
7 | from ctpbee import LooperApi, Vessel
8 | from ctpbee.constant import Direction
9 | from indicator.interface import Indicator
10 |
11 |
12 | def get_data(start, end, symbol, exchange, level):
13 | """ using rqdatac to make an example """
14 | # import rqdatac as rq
15 | # from rqdatac import get_price, id_convert
16 | # username = "license"
17 | # password = "NK-Ci7vnLsRiPPWYwxvvPYdYM90vxN60qUB5tVac2mQuvZ8f9Mq8K_nnUqVspOpi4BLTkSLgq8OQFpOOj7L" \
18 | # "t7AbdBZEBqRK74fIJH5vsaAfFQgl-tuB8l03axrW8cyN6-nBUho_6Y5VCRI63Mx_PN54nsQOpc1psIGEz" \
19 | # "gND8c6Y=bqMVlABkpSlrDNk4DgG-1QXNknJtk0Kkw2axvFDa0E_XPMqOcBxifuRa_DFI2svseXU-8A" \
20 | # "eLjchnTkeuvQkKh6nrfehVDiXjoMeq5sXgqpbgFAd4A5j2B1a0gpE3cb5kXb42n13fGwFaGris" \
21 | # "8-eKzz_jncvuAamkJEQQV0aLdiw="
22 | # host = "rqdatad-pro.ricequant.com"
23 | # port = 16011
24 | # rq.init(username, password, (host, port))
25 | # symbol_rq = id_convert(symbol)
26 | # data = get_price(symbol_rq, start_date=start, end_date=end, frequency=level, fields=None,
27 | # adjust_type='pre', skip_suspended=False, market='cn', expect_df=False)
28 | # origin = data.to_dict(orient='records')
29 | # result = []
30 | # for x in origin:
31 | # do = {}
32 | # do['open_price'] = x['open']
33 | # do['low_price'] = x['low']
34 | # do['high_price'] = x['high']
35 | # do['close_price'] = x['close']
36 | # do['datetime'] = datetime.strptime(str(x['trading_date']), "%Y-%m-%d %H:%M:%S")
37 | # do['symbol'] = symbol
38 | # do['local_symbol'] = symbol + "." + exchange
39 | # do['exchange'] = exchange
40 | # result.append(do)
41 | # return result
42 |
43 |
44 | def get_a_strategy():
45 | class SmaStrategy(LooperApi):
46 |
47 | def __init__(self, name):
48 | super().__init__(name)
49 | self.count = 1
50 | self.pos = 0
51 |
52 | self.bar_3 = Indicator() # 3分钟bar线
53 | self.bar_3.open_json('../zn1912.SHFE.json') # 读取本地数据
54 |
55 | self.allow_max_price = 5000 # 设置价格上限 当价格达到这个就卖出 防止突然跌
56 | self.allow_low_price = 2000 # 设置价格下限 当价格低出这里就卖 防止巨亏
57 |
58 | def on_bar(self, bar):
59 | # todo: RSI 相对强度指数
60 | """ """
61 | self.bar_3.add_bar(bar)
62 | if not self.bar_3.inited:
63 | return
64 | roc = self.bar_3.roc()
65 |
66 | if self.allow_max_price < bar.close_price and self.pos > 0:
67 | self.action.sell(bar.close_price, self.pos, bar)
68 |
69 | if self.allow_low_price > bar.close_price and self.pos > 0:
70 | self.action.sell(bar.close_price, self.pos, bar)
71 |
72 | ##################
73 | # 无具体资料 #
74 | ##################
75 | pass
76 |
77 | def on_trade(self, trade):
78 | if trade.direction == Direction.LONG:
79 | self.pos += trade.volume
80 | else:
81 | self.pos -= trade.volume
82 |
83 | def init_params(self, data):
84 | """"""
85 | # print("我在设置策略参数")
86 |
87 | return SmaStrategy("double_ma")
88 |
89 |
90 | def save_data_json(data):
91 | result = {"result": data}
92 |
93 | class CJsonEncoder(json.JSONEncoder):
94 | def default(self, obj):
95 | if isinstance(obj, datetime):
96 | return obj.strftime('%Y-%m-%d %H:%M:%S')
97 | elif isinstance(obj, date):
98 | return obj.strftime('%Y-%m-%d')
99 | else:
100 | return json.JSONEncoder.default(self, obj)
101 |
102 | with open("../data.json", "w") as f:
103 | json.dump(result, f, cls=CJsonEncoder)
104 |
105 |
106 | def load_data():
107 | with open("../data.json", "r") as f:
108 | data = json.load(f)
109 | return data.get("result")
110 |
111 |
112 | def run_main(data):
113 | vessel = Vessel()
114 | vessel.add_data(data)
115 | stra = get_a_strategy()
116 | vessel.add_strategy(stra)
117 | vessel.set_params({"looper":
118 | {"initial_capital": 100000,
119 | "commission": 0.005,
120 | "deal_pattern": "price",
121 | "size_map": {"ag1912.SHFE": 15},
122 | "today_commission": 0.005,
123 | "yesterday_commission": 0.02,
124 | "close_commission": 0.005,
125 | "slippage_sell": 0,
126 | "slippage_cover": 0,
127 | "slippage_buy": 0,
128 | "slippage_short": 0,
129 | "close_pattern": "yesterday",
130 | },
131 | "strategy": {}
132 | })
133 | vessel.run()
134 | from pprint import pprint
135 | result = vessel.get_result()
136 | pprint(result)
137 |
138 |
139 | if __name__ == '__main__':
140 | data = load_data()
141 | for x in data:
142 | x['datetime'] = datetime.strptime(str(x['datetime']), "%Y-%m-%d %H:%M:%S")
143 | run_main(data)
--------------------------------------------------------------------------------
/examples/sar_strategy.py:
--------------------------------------------------------------------------------
1 | """
2 | 简单抛物线sar策略 sar = info.sar()
3 | """
4 |
5 | import json
6 | from datetime import datetime, date
7 | from ctpbee import LooperApi, Vessel
8 | from ctpbee.constant import Direction
9 | from indicator.interface import Indicator
10 |
11 |
12 | def get_data(start, end, symbol, exchange, level):
13 | """ using rqdatac to make an example """
14 | # import rqdatac as rq
15 | # from rqdatac import get_price, id_convert
16 | # username = "license"
17 | # password = "NK-Ci7vnLsRiPPWYwxvvPYdYM90vxN60qUB5tVac2mQuvZ8f9Mq8K_nnUqVspOpi4BLTkSLgq8OQFpOOj7L" \
18 | # "t7AbdBZEBqRK74fIJH5vsaAfFQgl-tuB8l03axrW8cyN6-nBUho_6Y5VCRI63Mx_PN54nsQOpc1psIGEz" \
19 | # "gND8c6Y=bqMVlABkpSlrDNk4DgG-1QXNknJtk0Kkw2axvFDa0E_XPMqOcBxifuRa_DFI2svseXU-8A" \
20 | # "eLjchnTkeuvQkKh6nrfehVDiXjoMeq5sXgqpbgFAd4A5j2B1a0gpE3cb5kXb42n13fGwFaGris" \
21 | # "8-eKzz_jncvuAamkJEQQV0aLdiw="
22 | # host = "rqdatad-pro.ricequant.com"
23 | # port = 16011
24 | # rq.init(username, password, (host, port))
25 | # symbol_rq = id_convert(symbol)
26 | # data = get_price(symbol_rq, start_date=start, end_date=end, frequency=level, fields=None,
27 | # adjust_type='pre', skip_suspended=False, market='cn', expect_df=False)
28 | # origin = data.to_dict(orient='records')
29 | # result = []
30 | # for x in origin:
31 | # do = {}
32 | # do['open_price'] = x['open']
33 | # do['low_price'] = x['low']
34 | # do['high_price'] = x['high']
35 | # do['close_price'] = x['close']
36 | # do['datetime'] = datetime.strptime(str(x['trading_date']), "%Y-%m-%d %H:%M:%S")
37 | # do['symbol'] = symbol
38 | # do['local_symbol'] = symbol + "." + exchange
39 | # do['exchange'] = exchange
40 | # result.append(do)
41 | # return result
42 |
43 |
44 | def get_a_strategy():
45 | class SmaStrategy(LooperApi):
46 |
47 | def __init__(self, name):
48 | super().__init__(name)
49 | self.count = 1
50 | self.pos = 0
51 |
52 | self.bar_3 = Indicator() # 3分钟bar线
53 | self.bar_3.open_json('../zn1912.SHFE.json') # 读取本地数据
54 |
55 | self.allow_max_price = 5000 # 设置价格上限 当价格达到这个就卖出 防止突然跌
56 | self.allow_low_price = 2000 # 设置价格下限 当价格低出这里就卖 防止巨亏
57 |
58 | def on_bar(self, bar):
59 | # todo: 抛物线指标 SAR
60 | """ """
61 | self.bar_3.add_bar(bar)
62 | if not self.bar_3.inited:
63 | return
64 | sar = self.bar_3.sar()
65 |
66 | if self.allow_max_price < bar.close_price and self.pos > 0:
67 | self.action.sell(bar.close_price, self.pos, bar)
68 |
69 | if self.allow_low_price > bar.close_price and self.pos > 0:
70 | self.action.sell(bar.close_price, self.pos, bar)
71 |
72 | # 接连涨
73 | if sar[-1]['sar'] > sar[-2]['sar']:
74 | # 没有就买
75 | if self.pos == 0:
76 | self.action.buy(bar.close_price, 1, bar)
77 | elif self.pos < 0:
78 | self.action.cover(bar.close_price, 1, bar)
79 | self.action.buy(bar.close_price, 1, bar)
80 | else:
81 | if self.pos > 0:
82 | self.action.sell(bar.close_price, 1, bar)
83 | self.action.short(bar.close_price, 1, bar)
84 |
85 | def on_trade(self, trade):
86 | if trade.direction == Direction.LONG:
87 | self.pos += trade.volume
88 | else:
89 | self.pos -= trade.volume
90 | print(self.pos, '-----------')
91 |
92 | def init_params(self, data):
93 | """"""
94 | # print("我在设置策略参数")
95 |
96 | return SmaStrategy("double_ma")
97 |
98 |
99 | def save_data_json(data):
100 | result = {"result": data}
101 |
102 | class CJsonEncoder(json.JSONEncoder):
103 | def default(self, obj):
104 | if isinstance(obj, datetime):
105 | return obj.strftime('%Y-%m-%d %H:%M:%S')
106 | elif isinstance(obj, date):
107 | return obj.strftime('%Y-%m-%d')
108 | else:
109 | return json.JSONEncoder.default(self, obj)
110 |
111 | with open("../data.json", "w") as f:
112 | json.dump(result, f, cls=CJsonEncoder)
113 |
114 |
115 | def load_data():
116 | with open("../data.json", "r") as f:
117 | data = json.load(f)
118 | return data.get("result")
119 |
120 |
121 | def run_main(data):
122 | vessel = Vessel()
123 | vessel.add_data(data)
124 | stra = get_a_strategy()
125 | vessel.add_strategy(stra)
126 | vessel.set_params({"looper":
127 | {"initial_capital": 100000,
128 | "commission": 0.005,
129 | "deal_pattern": "price",
130 | "size_map": {"ag1912.SHFE": 15},
131 | "today_commission": 0.005,
132 | "yesterday_commission": 0.02,
133 | "close_commission": 0.005,
134 | "slippage_sell": 0,
135 | "slippage_cover": 0,
136 | "slippage_buy": 0,
137 | "slippage_short": 0,
138 | "close_pattern": "yesterday",
139 | },
140 | "strategy": {}
141 | })
142 | vessel.run()
143 | from pprint import pprint
144 | result = vessel.get_result()
145 | pprint(result)
146 |
147 |
148 | if __name__ == '__main__':
149 | data = load_data()
150 | for x in data:
151 | x['datetime'] = datetime.strptime(str(x['datetime']), "%Y-%m-%d %H:%M:%S")
152 | run_main(data)
--------------------------------------------------------------------------------
/examples/sma_strategy.py:
--------------------------------------------------------------------------------
1 | """
2 | 简单滑动平均线sma策略 sar = info.sma()
3 | """
4 |
5 | import json
6 | from datetime import datetime, date
7 | from ctpbee import LooperApi, Vessel
8 | from ctpbee.constant import Direction
9 | from indicator.interface import Indicator
10 |
11 |
12 | def get_data(start, end, symbol, exchange, level):
13 | """ using rqdatac to make an example """
14 | # import rqdatac as rq
15 | # from rqdatac import get_price, id_convert
16 | # username = "license"
17 | # password = "NK-Ci7vnLsRiPPWYwxvvPYdYM90vxN60qUB5tVac2mQuvZ8f9Mq8K_nnUqVspOpi4BLTkSLgq8OQFpOOj7L" \
18 | # "t7AbdBZEBqRK74fIJH5vsaAfFQgl-tuB8l03axrW8cyN6-nBUho_6Y5VCRI63Mx_PN54nsQOpc1psIGEz" \
19 | # "gND8c6Y=bqMVlABkpSlrDNk4DgG-1QXNknJtk0Kkw2axvFDa0E_XPMqOcBxifuRa_DFI2svseXU-8A" \
20 | # "eLjchnTkeuvQkKh6nrfehVDiXjoMeq5sXgqpbgFAd4A5j2B1a0gpE3cb5kXb42n13fGwFaGris" \
21 | # "8-eKzz_jncvuAamkJEQQV0aLdiw="
22 | # host = "rqdatad-pro.ricequant.com"
23 | # port = 16011
24 | # rq.init(username, password, (host, port))
25 | # symbol_rq = id_convert(symbol)
26 | # data = get_price(symbol_rq, start_date=start, end_date=end, frequency=level, fields=None,
27 | # adjust_type='pre', skip_suspended=False, market='cn', expect_df=False)
28 | # origin = data.to_dict(orient='records')
29 | # result = []
30 | # for x in origin:
31 | # do = {}
32 | # do['open_price'] = x['open']
33 | # do['low_price'] = x['low']
34 | # do['high_price'] = x['high']
35 | # do['close_price'] = x['close']
36 | # do['datetime'] = datetime.strptime(str(x['trading_date']), "%Y-%m-%d %H:%M:%S")
37 | # do['symbol'] = symbol
38 | # do['local_symbol'] = symbol + "." + exchange
39 | # do['exchange'] = exchange
40 | # result.append(do)
41 | # return result
42 |
43 |
44 | def get_a_strategy():
45 | class SmaStrategy(LooperApi):
46 |
47 | def __init__(self, name):
48 | super().__init__(name)
49 | self.count = 1
50 | self.pos = 0
51 |
52 | self.bar_3 = Indicator() # 3分钟bar线
53 | # self.bar_3.open_json('../zn1912.SHFE.json') # 读取本地数据
54 |
55 | self.allow_max_price = 5000 # 设置价格上限 当价格达到这个就卖出 防止突然跌
56 | self.allow_low_price = 2000 # 设置价格下限 当价格低出这里就卖 防止巨亏
57 |
58 | def on_bar(self, bar):
59 | # todo: 抛物线指标 SAR
60 | """ """
61 | self.bar_3.add_bar(bar)
62 | if not self.bar_3.inited:
63 | return
64 | close = self.bar_3.close
65 | sma = self.bar_3.sma()
66 |
67 | if self.allow_max_price < bar.close_price and self.pos > 0:
68 | self.action.sell(bar.close_price, self.pos, bar)
69 |
70 | if self.allow_low_price > bar.close_price and self.pos > 0:
71 | self.action.sell(bar.close_price, self.pos, bar)
72 |
73 | # 连涨就买
74 | if sma[-1] > sma[-2] and close[-1] > sma[-2]:
75 | # 没有就买
76 | if self.pos == 0:
77 | self.action.buy(bar.close_price, 1, bar)
78 | elif self.pos < 0:
79 | self.action.cover(bar.close_price, 1, bar)
80 | self.action.buy(bar.close_price, 1, bar)
81 | # 跌就卖
82 | else:
83 | if self.pos > 0:
84 | self.action.sell(bar.close_price, self.pos, bar)
85 | self.action.short(bar.close_price, self.pos, bar)
86 |
87 | def on_trade(self, trade):
88 | if trade.direction == Direction.LONG:
89 | self.pos += trade.volume
90 | else:
91 | self.pos -= trade.volume
92 |
93 | def init_params(self, data):
94 | """"""
95 | # print("我在设置策略参数")
96 |
97 | return SmaStrategy("double_ma")
98 |
99 |
100 | def save_data_json(data):
101 | result = {"result": data}
102 |
103 | class CJsonEncoder(json.JSONEncoder):
104 | def default(self, obj):
105 | if isinstance(obj, datetime):
106 | return obj.strftime('%Y-%m-%d %H:%M:%S')
107 | elif isinstance(obj, date):
108 | return obj.strftime('%Y-%m-%d')
109 | else:
110 | return json.JSONEncoder.default(self, obj)
111 |
112 | with open("../data.json", "w") as f:
113 | json.dump(result, f, cls=CJsonEncoder)
114 |
115 |
116 | def load_data():
117 | with open("../data.json", "r") as f:
118 | data = json.load(f)
119 | return data.get("result")
120 |
121 |
122 | def run_main(data):
123 | vessel = Vessel()
124 | vessel.add_data(data)
125 | stra = get_a_strategy()
126 | vessel.add_strategy(stra)
127 | vessel.set_params({"looper":
128 | {"initial_capital": 100000,
129 | "commission": 0.005,
130 | "deal_pattern": "price",
131 | "size_map": {"ag1912.SHFE": 15},
132 | "today_commission": 0.005,
133 | "yesterday_commission": 0.02,
134 | "close_commission": 0.005,
135 | "slippage_sell": 0,
136 | "slippage_cover": 0,
137 | "slippage_buy": 0,
138 | "slippage_short": 0,
139 | "close_pattern": "yesterday",
140 | },
141 | "strategy": {}
142 | })
143 | vessel.run()
144 | from pprint import pprint
145 | result = vessel.get_result()
146 | pprint(result)
147 |
148 |
149 | if __name__ == '__main__':
150 | data = load_data()
151 | for x in data:
152 | x['datetime'] = datetime.strptime(str(x['datetime']), "%Y-%m-%d %H:%M:%S")
153 | run_main(data)
--------------------------------------------------------------------------------
/examples/smma_strategy.py:
--------------------------------------------------------------------------------
1 | """
2 | 简单平均指标smma策略 smma = info.smma()
3 | """
4 |
5 | import json
6 | from datetime import datetime, date
7 | from ctpbee import LooperApi, Vessel
8 | from ctpbee.constant import Direction
9 | from indicator.interface import Indicator
10 |
11 |
12 | def get_data(start, end, symbol, exchange, level):
13 | """ using rqdatac to make an example """
14 | # import rqdatac as rq
15 | # from rqdatac import get_price, id_convert
16 | # username = "license"
17 | # password = "NK-Ci7vnLsRiPPWYwxvvPYdYM90vxN60qUB5tVac2mQuvZ8f9Mq8K_nnUqVspOpi4BLTkSLgq8OQFpOOj7L" \
18 | # "t7AbdBZEBqRK74fIJH5vsaAfFQgl-tuB8l03axrW8cyN6-nBUho_6Y5VCRI63Mx_PN54nsQOpc1psIGEz" \
19 | # "gND8c6Y=bqMVlABkpSlrDNk4DgG-1QXNknJtk0Kkw2axvFDa0E_XPMqOcBxifuRa_DFI2svseXU-8A" \
20 | # "eLjchnTkeuvQkKh6nrfehVDiXjoMeq5sXgqpbgFAd4A5j2B1a0gpE3cb5kXb42n13fGwFaGris" \
21 | # "8-eKzz_jncvuAamkJEQQV0aLdiw="
22 | # host = "rqdatad-pro.ricequant.com"
23 | # port = 16011
24 | # rq.init(username, password, (host, port))
25 | # symbol_rq = id_convert(symbol)
26 | # data = get_price(symbol_rq, start_date=start, end_date=end, frequency=level, fields=None,
27 | # adjust_type='pre', skip_suspended=False, market='cn', expect_df=False)
28 | # origin = data.to_dict(orient='records')
29 | # result = []
30 | # for x in origin:
31 | # do = {}
32 | # do['open_price'] = x['open']
33 | # do['low_price'] = x['low']
34 | # do['high_price'] = x['high']
35 | # do['close_price'] = x['close']
36 | # do['datetime'] = datetime.strptime(str(x['trading_date']), "%Y-%m-%d %H:%M:%S")
37 | # do['symbol'] = symbol
38 | # do['local_symbol'] = symbol + "." + exchange
39 | # do['exchange'] = exchange
40 | # result.append(do)
41 | # return result
42 |
43 |
44 | def get_a_strategy():
45 | class SmaStrategy(LooperApi):
46 |
47 | def __init__(self, name):
48 | super().__init__(name)
49 | self.count = 1
50 | self.pos = 0
51 |
52 | self.bar_3 = Indicator() # 3分钟bar线
53 | self.bar_3.open_json('../zn1912.SHFE.json') # 读取本地数据
54 |
55 | self.allow_max_price = 5000 # 设置价格上限 当价格达到这个就卖出 防止突然跌
56 | self.allow_low_price = 2000 # 设置价格下限 当价格低出这里就卖 防止巨亏
57 |
58 | def on_bar(self, bar):
59 | # todo: 简单平均指标 SMMA
60 | """ """
61 | self.bar_3.add_bar(bar)
62 | if not self.bar_3.inited:
63 | return
64 | sar = self.bar_3.sar()
65 |
66 | if self.allow_max_price < bar.close_price and self.pos > 0:
67 | self.action.sell(bar.close_price, self.pos, bar)
68 |
69 | if self.allow_low_price > bar.close_price and self.pos > 0:
70 | self.action.sell(bar.close_price, self.pos, bar)
71 |
72 | ###############
73 | # 暂时不写 #
74 | ###############
75 | pass
76 |
77 | def on_trade(self, trade):
78 | if trade.direction == Direction.LONG:
79 | self.pos += trade.volume
80 | else:
81 | self.pos -= trade.volume
82 | print(self.pos, '-----------')
83 |
84 | def init_params(self, data):
85 | """"""
86 | # print("我在设置策略参数")
87 |
88 | return SmaStrategy("double_ma")
89 |
90 |
91 | def save_data_json(data):
92 | result = {"result": data}
93 |
94 | class CJsonEncoder(json.JSONEncoder):
95 | def default(self, obj):
96 | if isinstance(obj, datetime):
97 | return obj.strftime('%Y-%m-%d %H:%M:%S')
98 | elif isinstance(obj, date):
99 | return obj.strftime('%Y-%m-%d')
100 | else:
101 | return json.JSONEncoder.default(self, obj)
102 |
103 | with open("../data.json", "w") as f:
104 | json.dump(result, f, cls=CJsonEncoder)
105 |
106 |
107 | def load_data():
108 | with open("../data.json", "r") as f:
109 | data = json.load(f)
110 | return data.get("result")
111 |
112 |
113 | def run_main(data):
114 | vessel = Vessel()
115 | vessel.add_data(data)
116 | stra = get_a_strategy()
117 | vessel.add_strategy(stra)
118 | vessel.set_params({"looper":
119 | {"initial_capital": 100000,
120 | "commission": 0.005,
121 | "deal_pattern": "price",
122 | "size_map": {"ag1912.SHFE": 15},
123 | "today_commission": 0.005,
124 | "yesterday_commission": 0.02,
125 | "close_commission": 0.005,
126 | "slippage_sell": 0,
127 | "slippage_cover": 0,
128 | "slippage_buy": 0,
129 | "slippage_short": 0,
130 | "close_pattern": "yesterday",
131 | },
132 | "strategy": {}
133 | })
134 | vessel.run()
135 | from pprint import pprint
136 | result = vessel.get_result()
137 | pprint(result)
138 |
139 |
140 | if __name__ == '__main__':
141 | data = load_data()
142 | for x in data:
143 | x['datetime'] = datetime.strptime(str(x['datetime']), "%Y-%m-%d %H:%M:%S")
144 | run_main(data)
--------------------------------------------------------------------------------
/examples/stdDev_strategy.py:
--------------------------------------------------------------------------------
1 | """
2 | 简单标准偏差StaDev策略 staDev = info.staDev()
3 | """
4 |
5 | import json
6 | from datetime import datetime, date
7 | from ctpbee import LooperApi, Vessel
8 | from ctpbee.constant import Direction
9 | from indicator.interface import Indicator
10 |
11 |
12 | def get_data(start, end, symbol, exchange, level):
13 | """ using rqdatac to make an example """
14 | # import rqdatac as rq
15 | # from rqdatac import get_price, id_convert
16 | # username = "license"
17 | # password = "NK-Ci7vnLsRiPPWYwxvvPYdYM90vxN60qUB5tVac2mQuvZ8f9Mq8K_nnUqVspOpi4BLTkSLgq8OQFpOOj7L" \
18 | # "t7AbdBZEBqRK74fIJH5vsaAfFQgl-tuB8l03axrW8cyN6-nBUho_6Y5VCRI63Mx_PN54nsQOpc1psIGEz" \
19 | # "gND8c6Y=bqMVlABkpSlrDNk4DgG-1QXNknJtk0Kkw2axvFDa0E_XPMqOcBxifuRa_DFI2svseXU-8A" \
20 | # "eLjchnTkeuvQkKh6nrfehVDiXjoMeq5sXgqpbgFAd4A5j2B1a0gpE3cb5kXb42n13fGwFaGris" \
21 | # "8-eKzz_jncvuAamkJEQQV0aLdiw="
22 | # host = "rqdatad-pro.ricequant.com"
23 | # port = 16011
24 | # rq.init(username, password, (host, port))
25 | # symbol_rq = id_convert(symbol)
26 | # data = get_price(symbol_rq, start_date=start, end_date=end, frequency=level, fields=None,
27 | # adjust_type='pre', skip_suspended=False, market='cn', expect_df=False)
28 | # origin = data.to_dict(orient='records')
29 | # result = []
30 | # for x in origin:
31 | # do = {}
32 | # do['open_price'] = x['open']
33 | # do['low_price'] = x['low']
34 | # do['high_price'] = x['high']
35 | # do['close_price'] = x['close']
36 | # do['datetime'] = datetime.strptime(str(x['trading_date']), "%Y-%m-%d %H:%M:%S")
37 | # do['symbol'] = symbol
38 | # do['local_symbol'] = symbol + "." + exchange
39 | # do['exchange'] = exchange
40 | # result.append(do)
41 | # return result
42 |
43 |
44 | def get_a_strategy():
45 | class SmaStrategy(LooperApi):
46 |
47 | def __init__(self, name):
48 | super().__init__(name)
49 | self.count = 1
50 | self.pos = 0
51 |
52 | self.bar_3 = Indicator() # 3分钟bar线
53 | self.bar_3.open_json('../zn1912.SHFE.json') # 读取本地数据
54 |
55 | self.allow_max_price = 5000 # 设置价格上限 当价格达到这个就卖出 防止突然跌
56 | self.allow_low_price = 2000 # 设置价格下限 当价格低出这里就卖 防止巨亏
57 |
58 | def on_bar(self, bar):
59 | # todo: 标准偏差 stdDev
60 | """ """
61 | self.bar_3.add_bar(bar)
62 | if not self.bar_3.inited:
63 | return
64 | stdDev = self.bar_3.stdDev()
65 |
66 | if self.allow_max_price < bar.close_price and self.pos > 0:
67 | self.action.sell(bar.close_price, self.pos, bar)
68 |
69 | if self.allow_low_price > bar.close_price and self.pos > 0:
70 | self.action.sell(bar.close_price, self.pos, bar)
71 |
72 | ############
73 | # 暂时不写 #
74 | ###########
75 | pass
76 |
77 | def on_trade(self, trade):
78 | if trade.direction == Direction.LONG:
79 | self.pos += trade.volume
80 | else:
81 | self.pos -= trade.volume
82 |
83 | def init_params(self, data):
84 | """"""
85 | # print("我在设置策略参数")
86 |
87 | return SmaStrategy("double_ma")
88 |
89 |
90 | def save_data_json(data):
91 | result = {"result": data}
92 |
93 | class CJsonEncoder(json.JSONEncoder):
94 | def default(self, obj):
95 | if isinstance(obj, datetime):
96 | return obj.strftime('%Y-%m-%d %H:%M:%S')
97 | elif isinstance(obj, date):
98 | return obj.strftime('%Y-%m-%d')
99 | else:
100 | return json.JSONEncoder.default(self, obj)
101 |
102 | with open("../data.json", "w") as f:
103 | json.dump(result, f, cls=CJsonEncoder)
104 |
105 |
106 | def load_data():
107 | with open("../data.json", "r") as f:
108 | data = json.load(f)
109 | return data.get("result")
110 |
111 |
112 | def run_main(data):
113 | vessel = Vessel()
114 | vessel.add_data(data)
115 | stra = get_a_strategy()
116 | vessel.add_strategy(stra)
117 | vessel.set_params({"looper":
118 | {"initial_capital": 100000,
119 | "commission": 0.005,
120 | "deal_pattern": "price",
121 | "size_map": {"ag1912.SHFE": 15},
122 | "today_commission": 0.005,
123 | "yesterday_commission": 0.02,
124 | "close_commission": 0.005,
125 | "slippage_sell": 0,
126 | "slippage_cover": 0,
127 | "slippage_buy": 0,
128 | "slippage_short": 0,
129 | "close_pattern": "yesterday",
130 | },
131 | "strategy": {}
132 | })
133 | vessel.run()
134 | from pprint import pprint
135 | result = vessel.get_result()
136 | pprint(result)
137 |
138 |
139 | if __name__ == '__main__':
140 | data = load_data()
141 | for x in data:
142 | x['datetime'] = datetime.strptime(str(x['datetime']), "%Y-%m-%d %H:%M:%S")
143 | run_main(data)
--------------------------------------------------------------------------------
/examples/tema_strategy.py:
--------------------------------------------------------------------------------
1 | """
2 | 简单三倍运动平均值tema策略 tema = info.tema()
3 | """
4 |
5 | import json
6 | from datetime import datetime, date
7 | from ctpbee import LooperApi, Vessel
8 | from ctpbee.constant import Direction
9 | from indicator.interface import Indicator
10 |
11 |
12 | def get_data(start, end, symbol, exchange, level):
13 | """ using rqdatac to make an example """
14 | # import rqdatac as rq
15 | # from rqdatac import get_price, id_convert
16 | # username = "license"
17 | # password = "NK-Ci7vnLsRiPPWYwxvvPYdYM90vxN60qUB5tVac2mQuvZ8f9Mq8K_nnUqVspOpi4BLTkSLgq8OQFpOOj7L" \
18 | # "t7AbdBZEBqRK74fIJH5vsaAfFQgl-tuB8l03axrW8cyN6-nBUho_6Y5VCRI63Mx_PN54nsQOpc1psIGEz" \
19 | # "gND8c6Y=bqMVlABkpSlrDNk4DgG-1QXNknJtk0Kkw2axvFDa0E_XPMqOcBxifuRa_DFI2svseXU-8A" \
20 | # "eLjchnTkeuvQkKh6nrfehVDiXjoMeq5sXgqpbgFAd4A5j2B1a0gpE3cb5kXb42n13fGwFaGris" \
21 | # "8-eKzz_jncvuAamkJEQQV0aLdiw="
22 | # host = "rqdatad-pro.ricequant.com"
23 | # port = 16011
24 | # rq.init(username, password, (host, port))
25 | # symbol_rq = id_convert(symbol)
26 | # data = get_price(symbol_rq, start_date=start, end_date=end, frequency=level, fields=None,
27 | # adjust_type='pre', skip_suspended=False, market='cn', expect_df=False)
28 | # origin = data.to_dict(orient='records')
29 | # result = []
30 | # for x in origin:
31 | # do = {}
32 | # do['open_price'] = x['open']
33 | # do['low_price'] = x['low']
34 | # do['high_price'] = x['high']
35 | # do['close_price'] = x['close']
36 | # do['datetime'] = datetime.strptime(str(x['trading_date']), "%Y-%m-%d %H:%M:%S")
37 | # do['symbol'] = symbol
38 | # do['local_symbol'] = symbol + "." + exchange
39 | # do['exchange'] = exchange
40 | # result.append(do)
41 | # return result
42 |
43 |
44 | def get_a_strategy():
45 | class SmaStrategy(LooperApi):
46 |
47 | def __init__(self, name):
48 | super().__init__(name)
49 | self.count = 1
50 | self.pos = 0
51 |
52 | self.bar_3 = Indicator() # 3分钟bar线
53 | self.bar_3.open_json('../zn1912.SHFE.json') # 读取本地数据
54 |
55 | self.allow_max_price = 5000 # 设置价格上限 当价格达到这个就卖出 防止突然跌
56 | self.allow_low_price = 2000 # 设置价格下限 当价格低出这里就卖 防止巨亏
57 |
58 | def on_bar(self, bar):
59 | # todo: 三倍运动平均值指标 TEMA
60 | """ """
61 | self.bar_3.add_bar(bar)
62 | if not self.bar_3.inited:
63 | return
64 | close = self.bar_3.close
65 | tema = self.bar_3.tema()
66 |
67 | if self.allow_max_price < bar.close_price and self.pos > 0:
68 | self.action.sell(bar.close_price, self.pos, bar)
69 |
70 | if self.allow_low_price > bar.close_price and self.pos > 0:
71 | self.action.sell(bar.close_price, self.pos, bar)
72 |
73 | # 三倍平均数小于收盘价
74 | if tema[-1] < close[-1]:
75 | # 没有就买
76 | if self.pos == 0:
77 | self.action.buy(bar.close_price, 1, bar)
78 | elif self.pos < 0:
79 | self.action.cover(bar.close_price, 1, bar)
80 | self.action.buy(bar.close_price, 1, bar)
81 | else:
82 | if self.pos > 0:
83 | self.action.sell(bar.close_price, 1, bar)
84 | self.action.short(bar.close_price, 1, bar)
85 |
86 | def on_trade(self, trade):
87 | if trade.direction == Direction.LONG:
88 | self.pos += trade.volume
89 | else:
90 | self.pos -= trade.volume
91 |
92 | def init_params(self, data):
93 | """"""
94 | # print("我在设置策略参数")
95 |
96 | return SmaStrategy("double_ma")
97 |
98 |
99 | def save_data_json(data):
100 | result = {"result": data}
101 |
102 | class CJsonEncoder(json.JSONEncoder):
103 | def default(self, obj):
104 | if isinstance(obj, datetime):
105 | return obj.strftime('%Y-%m-%d %H:%M:%S')
106 | elif isinstance(obj, date):
107 | return obj.strftime('%Y-%m-%d')
108 | else:
109 | return json.JSONEncoder.default(self, obj)
110 |
111 | with open("../data.json", "w") as f:
112 | json.dump(result, f, cls=CJsonEncoder)
113 |
114 |
115 | def load_data():
116 | with open("../data.json", "r") as f:
117 | data = json.load(f)
118 | return data.get("result")
119 |
120 |
121 | def run_main(data):
122 | vessel = Vessel()
123 | vessel.add_data(data)
124 | stra = get_a_strategy()
125 | vessel.add_strategy(stra)
126 | vessel.set_params({"looper":
127 | {"initial_capital": 100000,
128 | "commission": 0.005,
129 | "deal_pattern": "price",
130 | "size_map": {"ag1912.SHFE": 15},
131 | "today_commission": 0.005,
132 | "yesterday_commission": 0.02,
133 | "close_commission": 0.005,
134 | "slippage_sell": 0,
135 | "slippage_cover": 0,
136 | "slippage_buy": 0,
137 | "slippage_short": 0,
138 | "close_pattern": "yesterday",
139 | },
140 | "strategy": {}
141 | })
142 | vessel.run()
143 | from pprint import pprint
144 | result = vessel.get_result()
145 | pprint(result)
146 |
147 |
148 | if __name__ == '__main__':
149 | data = load_data()
150 | for x in data:
151 | x['datetime'] = datetime.strptime(str(x['datetime']), "%Y-%m-%d %H:%M:%S")
152 | run_main(data)
--------------------------------------------------------------------------------
/examples/trix_strategy.py:
--------------------------------------------------------------------------------
1 | """
2 | 简单三重指数平滑移动平均trix策略 trix = info.trix()
3 | """
4 |
5 | import json
6 | from datetime import datetime, date
7 | from ctpbee import LooperApi, Vessel
8 | from ctpbee.constant import Direction
9 | from indicator.interface import Indicator
10 |
11 |
12 | def get_data(start, end, symbol, exchange, level):
13 | """ using rqdatac to make an example """
14 | # import rqdatac as rq
15 | # from rqdatac import get_price, id_convert
16 | # username = "license"
17 | # password = "NK-Ci7vnLsRiPPWYwxvvPYdYM90vxN60qUB5tVac2mQuvZ8f9Mq8K_nnUqVspOpi4BLTkSLgq8OQFpOOj7L" \
18 | # "t7AbdBZEBqRK74fIJH5vsaAfFQgl-tuB8l03axrW8cyN6-nBUho_6Y5VCRI63Mx_PN54nsQOpc1psIGEz" \
19 | # "gND8c6Y=bqMVlABkpSlrDNk4DgG-1QXNknJtk0Kkw2axvFDa0E_XPMqOcBxifuRa_DFI2svseXU-8A" \
20 | # "eLjchnTkeuvQkKh6nrfehVDiXjoMeq5sXgqpbgFAd4A5j2B1a0gpE3cb5kXb42n13fGwFaGris" \
21 | # "8-eKzz_jncvuAamkJEQQV0aLdiw="
22 | # host = "rqdatad-pro.ricequant.com"
23 | # port = 16011
24 | # rq.init(username, password, (host, port))
25 | # symbol_rq = id_convert(symbol)
26 | # data = get_price(symbol_rq, start_date=start, end_date=end, frequency=level, fields=None,
27 | # adjust_type='pre', skip_suspended=False, market='cn', expect_df=False)
28 | # origin = data.to_dict(orient='records')
29 | # result = []
30 | # for x in origin:
31 | # do = {}
32 | # do['open_price'] = x['open']
33 | # do['low_price'] = x['low']
34 | # do['high_price'] = x['high']
35 | # do['close_price'] = x['close']
36 | # do['datetime'] = datetime.strptime(str(x['trading_date']), "%Y-%m-%d %H:%M:%S")
37 | # do['symbol'] = symbol
38 | # do['local_symbol'] = symbol + "." + exchange
39 | # do['exchange'] = exchange
40 | # result.append(do)
41 | # return result
42 |
43 |
44 | def get_a_strategy():
45 | class SmaStrategy(LooperApi):
46 |
47 | def __init__(self, name):
48 | super().__init__(name)
49 | self.count = 1
50 | self.pos = 0
51 |
52 | self.bar_3 = Indicator() # 3分钟bar线
53 | self.bar_3.open_json('../zn1912.SHFE.json') # 读取本地数据
54 |
55 | self.allow_max_price = 5000 # 设置价格上限 当价格达到这个就卖出 防止突然跌
56 | self.allow_low_price = 2000 # 设置价格下限 当价格低出这里就卖 防止巨亏
57 |
58 | def on_bar(self, bar):
59 | # todo: 三重指数平滑移动平均 TRIX
60 | """ """
61 | self.bar_3.add_bar(bar)
62 | if not self.bar_3.inited:
63 | return
64 | trix = self.bar_3.trix()
65 | if self.allow_max_price < bar.close_price and self.pos > 0:
66 | self.action.sell(bar.close_price, self.pos, bar)
67 |
68 | if self.allow_low_price > bar.close_price and self.pos > 0:
69 | self.action.sell(bar.close_price, self.pos, bar)
70 |
71 | ##############
72 | # 暂时不写 #
73 | #############
74 | pass
75 |
76 |
77 | def on_trade(self, trade):
78 | if trade.direction == Direction.LONG:
79 | self.pos += trade.volume
80 | else:
81 | self.pos -= trade.volume
82 |
83 | def init_params(self, data):
84 | """"""
85 | # print("我在设置策略参数")
86 |
87 | return SmaStrategy("double_ma")
88 |
89 |
90 | def save_data_json(data):
91 | result = {"result": data}
92 |
93 | class CJsonEncoder(json.JSONEncoder):
94 | def default(self, obj):
95 | if isinstance(obj, datetime):
96 | return obj.strftime('%Y-%m-%d %H:%M:%S')
97 | elif isinstance(obj, date):
98 | return obj.strftime('%Y-%m-%d')
99 | else:
100 | return json.JSONEncoder.default(self, obj)
101 |
102 | with open("../data.json", "w") as f:
103 | json.dump(result, f, cls=CJsonEncoder)
104 |
105 |
106 | def load_data():
107 | with open("../data.json", "r") as f:
108 | data = json.load(f)
109 | return data.get("result")
110 |
111 |
112 | def run_main(data):
113 | vessel = Vessel()
114 | vessel.add_data(data)
115 | stra = get_a_strategy()
116 | vessel.add_strategy(stra)
117 | vessel.set_params({"looper":
118 | {"initial_capital": 100000,
119 | "commission": 0.005,
120 | "deal_pattern": "price",
121 | "size_map": {"ag1912.SHFE": 15},
122 | "today_commission": 0.005,
123 | "yesterday_commission": 0.02,
124 | "close_commission": 0.005,
125 | "slippage_sell": 0,
126 | "slippage_cover": 0,
127 | "slippage_buy": 0,
128 | "slippage_short": 0,
129 | "close_pattern": "yesterday",
130 | },
131 | "strategy": {}
132 | })
133 | vessel.run()
134 | from pprint import pprint
135 | result = vessel.get_result()
136 | pprint(result)
137 |
138 |
139 | if __name__ == '__main__':
140 | data = load_data()
141 | for x in data:
142 | x['datetime'] = datetime.strptime(str(x['datetime']), "%Y-%m-%d %H:%M:%S")
143 | run_main(data)
--------------------------------------------------------------------------------
/examples/wma_strategy.py:
--------------------------------------------------------------------------------
1 | """
2 | 简单加权移动平均线wma策略 wma = info.wma()
3 | """
4 |
5 | import json
6 | from datetime import datetime, date
7 | from ctpbee import LooperApi, Vessel
8 | from ctpbee.constant import Direction
9 | from indicator.interface import Indicator
10 |
11 |
12 | def get_data(start, end, symbol, exchange, level):
13 | """ using rqdatac to make an example """
14 | # import rqdatac as rq
15 | # from rqdatac import get_price, id_convert
16 | # username = "license"
17 | # password = "NK-Ci7vnLsRiPPWYwxvvPYdYM90vxN60qUB5tVac2mQuvZ8f9Mq8K_nnUqVspOpi4BLTkSLgq8OQFpOOj7L" \
18 | # "t7AbdBZEBqRK74fIJH5vsaAfFQgl-tuB8l03axrW8cyN6-nBUho_6Y5VCRI63Mx_PN54nsQOpc1psIGEz" \
19 | # "gND8c6Y=bqMVlABkpSlrDNk4DgG-1QXNknJtk0Kkw2axvFDa0E_XPMqOcBxifuRa_DFI2svseXU-8A" \
20 | # "eLjchnTkeuvQkKh6nrfehVDiXjoMeq5sXgqpbgFAd4A5j2B1a0gpE3cb5kXb42n13fGwFaGris" \
21 | # "8-eKzz_jncvuAamkJEQQV0aLdiw="
22 | # host = "rqdatad-pro.ricequant.com"
23 | # port = 16011
24 | # rq.init(username, password, (host, port))
25 | # symbol_rq = id_convert(symbol)
26 | # data = get_price(symbol_rq, start_date=start, end_date=end, frequency=level, fields=None,
27 | # adjust_type='pre', skip_suspended=False, market='cn', expect_df=False)
28 | # origin = data.to_dict(orient='records')
29 | # result = []
30 | # for x in origin:
31 | # do = {}
32 | # do['open_price'] = x['open']
33 | # do['low_price'] = x['low']
34 | # do['high_price'] = x['high']
35 | # do['close_price'] = x['close']
36 | # do['datetime'] = datetime.strptime(str(x['trading_date']), "%Y-%m-%d %H:%M:%S")
37 | # do['symbol'] = symbol
38 | # do['local_symbol'] = symbol + "." + exchange
39 | # do['exchange'] = exchange
40 | # result.append(do)
41 | # return result
42 |
43 |
44 | def get_a_strategy():
45 | class SmaStrategy(LooperApi):
46 |
47 | def __init__(self, name):
48 | super().__init__(name)
49 | self.count = 1
50 | self.pos = 0
51 |
52 | self.bar_3 = Indicator() # 3分钟bar线
53 | self.bar_3.open_json('../zn1912.SHFE.json') # 读取本地数据
54 |
55 | self.allow_max_price = 5000 # 设置价格上限 当价格达到这个就卖出 防止突然跌
56 | self.allow_low_price = 2000 # 设置价格下限 当价格低出这里就卖 防止巨亏
57 |
58 | def on_bar(self, bar):
59 | # todo: 加权移动平均线 WMA
60 | """ """
61 | self.bar_3.add_bar(bar)
62 | if not self.bar_3.inited:
63 | return
64 | wma = self.bar_3.wma()
65 |
66 | if self.allow_max_price < bar.close_price and self.pos > 0:
67 | self.action.sell(bar.close_price, self.pos, bar)
68 |
69 | if self.allow_low_price > bar.close_price and self.pos > 0:
70 | self.action.sell(bar.close_price, self.pos, bar)
71 |
72 | # 接连三天涨
73 | if wma[-1] > wma[-2]:
74 | # 没有就买
75 | if self.pos == 0:
76 | self.action.buy(bar.close_price, 1, bar)
77 | elif self.pos < 0:
78 | self.action.cover(bar.close_price, 1, bar)
79 | self.action.buy(bar.close_price, 1, bar)
80 | else:
81 | if self.pos > 0:
82 | self.action.sell(bar.close_price, 1, bar)
83 | self.action.short(bar.close_price, 1, bar)
84 |
85 | def on_trade(self, trade):
86 | if trade.direction == Direction.LONG:
87 | self.pos += trade.volume
88 | else:
89 | self.pos -= trade.volume
90 |
91 | def init_params(self, data):
92 | """"""
93 | # print("我在设置策略参数")
94 |
95 | return SmaStrategy("double_ma")
96 |
97 |
98 | def save_data_json(data):
99 | result = {"result": data}
100 |
101 | class CJsonEncoder(json.JSONEncoder):
102 | def default(self, obj):
103 | if isinstance(obj, datetime):
104 | return obj.strftime('%Y-%m-%d %H:%M:%S')
105 | elif isinstance(obj, date):
106 | return obj.strftime('%Y-%m-%d')
107 | else:
108 | return json.JSONEncoder.default(self, obj)
109 |
110 | with open("../data.json", "w") as f:
111 | json.dump(result, f, cls=CJsonEncoder)
112 |
113 |
114 | def load_data():
115 | with open("../data.json", "r") as f:
116 | data = json.load(f)
117 | return data.get("result")
118 |
119 |
120 | def run_main(data):
121 | vessel = Vessel()
122 | vessel.add_data(data)
123 | stra = get_a_strategy()
124 | vessel.add_strategy(stra)
125 | vessel.set_params({"looper":
126 | {"initial_capital": 100000,
127 | "commission": 0.005,
128 | "deal_pattern": "price",
129 | "size_map": {"ag1912.SHFE": 15},
130 | "today_commission": 0.005,
131 | "yesterday_commission": 0.02,
132 | "close_commission": 0.005,
133 | "slippage_sell": 0,
134 | "slippage_cover": 0,
135 | "slippage_buy": 0,
136 | "slippage_short": 0,
137 | "close_pattern": "yesterday",
138 | },
139 | "strategy": {}
140 | })
141 | vessel.run()
142 | from pprint import pprint
143 | result = vessel.get_result()
144 | pprint(result)
145 |
146 |
147 | if __name__ == '__main__':
148 | data = load_data()
149 | for x in data:
150 | x['datetime'] = datetime.strptime(str(x['datetime']), "%Y-%m-%d %H:%M:%S")
151 | run_main(data)
--------------------------------------------------------------------------------
/examples/wr_strategy.py:
--------------------------------------------------------------------------------
1 | """
2 | 简单威廉姆斯wr策略 wr = info.wr()
3 | """
4 |
5 | import json
6 | from datetime import datetime, date
7 | from ctpbee import LooperApi, Vessel
8 | from ctpbee.constant import Direction
9 | from indicator.interface import Indicator
10 |
11 |
12 | def get_data(start, end, symbol, exchange, level):
13 | """ using rqdatac to make an example """
14 | # import rqdatac as rq
15 | # from rqdatac import get_price, id_convert
16 | # username = "license"
17 | # password = "NK-Ci7vnLsRiPPWYwxvvPYdYM90vxN60qUB5tVac2mQuvZ8f9Mq8K_nnUqVspOpi4BLTkSLgq8OQFpOOj7L" \
18 | # "t7AbdBZEBqRK74fIJH5vsaAfFQgl-tuB8l03axrW8cyN6-nBUho_6Y5VCRI63Mx_PN54nsQOpc1psIGEz" \
19 | # "gND8c6Y=bqMVlABkpSlrDNk4DgG-1QXNknJtk0Kkw2axvFDa0E_XPMqOcBxifuRa_DFI2svseXU-8A" \
20 | # "eLjchnTkeuvQkKh6nrfehVDiXjoMeq5sXgqpbgFAd4A5j2B1a0gpE3cb5kXb42n13fGwFaGris" \
21 | # "8-eKzz_jncvuAamkJEQQV0aLdiw="
22 | # host = "rqdatad-pro.ricequant.com"
23 | # port = 16011
24 | # rq.init(username, password, (host, port))
25 | # symbol_rq = id_convert(symbol)
26 | # data = get_price(symbol_rq, start_date=start, end_date=end, frequency=level, fields=None,
27 | # adjust_type='pre', skip_suspended=False, market='cn', expect_df=False)
28 | # origin = data.to_dict(orient='records')
29 | # result = []
30 | # for x in origin:
31 | # do = {}
32 | # do['open_price'] = x['open']
33 | # do['low_price'] = x['low']
34 | # do['high_price'] = x['high']
35 | # do['close_price'] = x['close']
36 | # do['datetime'] = datetime.strptime(str(x['trading_date']), "%Y-%m-%d %H:%M:%S")
37 | # do['symbol'] = symbol
38 | # do['local_symbol'] = symbol + "." + exchange
39 | # do['exchange'] = exchange
40 | # result.append(do)
41 | # return result
42 |
43 |
44 | def get_a_strategy():
45 | class SmaStrategy(LooperApi):
46 |
47 | def __init__(self, name):
48 | super().__init__(name)
49 | self.count = 1
50 | self.pos = 0
51 |
52 | self.bar_3 = Indicator() # 3分钟bar线
53 | self.bar_3.open_json('../zn1912.SHFE.json') # 读取本地数据
54 |
55 | self.allow_max_price = 5000 # 设置价格上限 当价格达到这个就卖出 防止突然跌
56 | self.allow_low_price = 2000 # 设置价格下限 当价格低出这里就卖 防止巨亏
57 |
58 | def on_bar(self, bar):
59 | # todo: 威廉姆斯 WR
60 | """ """
61 | self.bar_3.add_bar(bar)
62 | if not self.bar_3.inited:
63 | return
64 | wr = self.bar_3.wr()
65 |
66 | if self.allow_max_price < bar.close_price and self.pos > 0:
67 | self.action.sell(bar.close_price, self.pos, bar)
68 |
69 | if self.allow_low_price > bar.close_price and self.pos > 0:
70 | self.action.sell(bar.close_price, self.pos, bar)
71 |
72 | #############
73 | # 暂时不写 #
74 | ############
75 | pass
76 |
77 | def on_trade(self, trade):
78 | if trade.direction == Direction.LONG:
79 | self.pos += trade.volume
80 | else:
81 | self.pos -= trade.volume
82 |
83 | def init_params(self, data):
84 | """"""
85 | # print("我在设置策略参数")
86 |
87 | return SmaStrategy("double_ma")
88 |
89 |
90 | def save_data_json(data):
91 | result = {"result": data}
92 |
93 | class CJsonEncoder(json.JSONEncoder):
94 | def default(self, obj):
95 | if isinstance(obj, datetime):
96 | return obj.strftime('%Y-%m-%d %H:%M:%S')
97 | elif isinstance(obj, date):
98 | return obj.strftime('%Y-%m-%d')
99 | else:
100 | return json.JSONEncoder.default(self, obj)
101 |
102 | with open("../data.json", "w") as f:
103 | json.dump(result, f, cls=CJsonEncoder)
104 |
105 |
106 | def load_data():
107 | with open("../data.json", "r") as f:
108 | data = json.load(f)
109 | return data.get("result")
110 |
111 |
112 | def run_main(data):
113 | vessel = Vessel()
114 | vessel.add_data(data)
115 | stra = get_a_strategy()
116 | vessel.add_strategy(stra)
117 | vessel.set_params({"looper":
118 | {"initial_capital": 100000,
119 | "commission": 0.005,
120 | "deal_pattern": "price",
121 | "size_map": {"ag1912.SHFE": 15},
122 | "today_commission": 0.005,
123 | "yesterday_commission": 0.02,
124 | "close_commission": 0.005,
125 | "slippage_sell": 0,
126 | "slippage_cover": 0,
127 | "slippage_buy": 0,
128 | "slippage_short": 0,
129 | "close_pattern": "yesterday",
130 | },
131 | "strategy": {}
132 | })
133 | vessel.run()
134 | from pprint import pprint
135 | result = vessel.get_result()
136 | pprint(result)
137 |
138 |
139 | if __name__ == '__main__':
140 | data = load_data()
141 | for x in data:
142 | x['datetime'] = datetime.strptime(str(x['datetime']), "%Y-%m-%d %H:%M:%S")
143 | run_main(data)
--------------------------------------------------------------------------------
/indicator/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ctpbee/ctpbee_indicator/d7a4d981eaf9e60b640d8f56b1bfb9b270269649/indicator/__init__.py
--------------------------------------------------------------------------------
/indicator/__pycache__/__init__.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ctpbee/ctpbee_indicator/d7a4d981eaf9e60b640d8f56b1bfb9b270269649/indicator/__pycache__/__init__.cpython-37.pyc
--------------------------------------------------------------------------------
/indicator/__pycache__/indicator.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ctpbee/ctpbee_indicator/d7a4d981eaf9e60b640d8f56b1bfb9b270269649/indicator/__pycache__/indicator.cpython-37.pyc
--------------------------------------------------------------------------------
/indicator/__pycache__/interface.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ctpbee/ctpbee_indicator/d7a4d981eaf9e60b640d8f56b1bfb9b270269649/indicator/__pycache__/interface.cpython-37.pyc
--------------------------------------------------------------------------------
/indicator/__pycache__/plot.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ctpbee/ctpbee_indicator/d7a4d981eaf9e60b640d8f56b1bfb9b270269649/indicator/__pycache__/plot.cpython-37.pyc
--------------------------------------------------------------------------------
/indicator/__pycache__/readfile.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ctpbee/ctpbee_indicator/d7a4d981eaf9e60b640d8f56b1bfb9b270269649/indicator/__pycache__/readfile.cpython-37.pyc
--------------------------------------------------------------------------------
/indicator/indicator.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | from .readfile import File
3 | import math
4 | import operator
5 | from copy import deepcopy
6 | from functools import wraps
7 |
8 |
9 | def getAverageName(func):
10 | """
11 | 此装饰器是获取平均平均值参数名
12 | :param func:
13 | :return:
14 | """
15 | @wraps(func)
16 | def wrapper(self, *args, **kwargs):
17 | line = func(self, *args, **kwargs)
18 | func_name = func.__name__
19 | self.average_message[func_name] = line
20 | return line
21 | return wrapper
22 |
23 |
24 | def getIndicatorName(func):
25 | """
26 | 此装饰器是获取其他指标值参数名
27 | :param func:
28 | :return:
29 | """
30 | @wraps(func)
31 | def wrapper(self, *args, **kwargs):
32 | line = func(self, *args, **kwargs)
33 | func_name = func.__name__
34 | if func_name == "macd":
35 | self.indicator_message["MACD"] = self.macds
36 | self.indicator_message["signal"] = self.signal
37 | self.indicator_message[func_name] = self.histo
38 | elif func_name == "kd":
39 | self.indicator_message["K"] = self.k
40 | self.indicator_message["D"] = self.percD
41 | elif func_name == "boll":
42 | self.indicator_message["mid"] = self.mid
43 | self.indicator_message["top"] = self.top
44 | self.indicator_message["bottom"] = self.bottom
45 | else:
46 | self.indicator_message[func_name] = line
47 | return line
48 | return wrapper
49 |
50 |
51 | class Indicator(File):
52 | def __init__(self):
53 | super().__init__()
54 | self.inited = False # 是否满足计算要求
55 | self.average_message = {}
56 | self.indicator_message = {}
57 |
58 | def calculate(self):
59 | """
60 | 计算指标
61 | :return:
62 | """
63 | pass
64 |
65 | @getAverageName
66 | def ma(self, data: object, period=5):
67 | """
68 | 均线
69 | :param data:
70 | :param period:
71 | :return:
72 | """
73 | end = len(data)
74 | if not self.inited:
75 | if end < period:
76 | return
77 | else:
78 | self.inited = True
79 | self.ma_data = deepcopy(data)
80 | for i in range(period, end):
81 | self.ma_data = sum(data[i-period:i+1])/period
82 | return self.ma_data
83 |
84 | @getAverageName
85 | def sma(self, data:object, period=15):
86 | """
87 | sma or ma SimpleMovingAverage
88 | 简单移动平均线
89 | :param period:距离
90 | :param data:数据 object
91 | :return:计算值
92 | """
93 | end = len(data)
94 | if not self.inited:
95 | if end < period:
96 | return
97 | else:
98 | self.inited = True
99 | self.sma_data = deepcopy(data)
100 | close_line = data
101 | for i in range(period, end):
102 | self.sma_data[i] = sum(close_line[i - period + 1:i + 1]) / period
103 | return self.sma_data
104 |
105 | @getAverageName
106 | def ema(self, data:object, period:int, alpha=None):
107 | """
108 | ema ExponentialMovingAverage
109 | 指数移动平均(period一般取12和26天)
110 | - self.smfactor -> 2 / (1 + period)
111 | - self.smfactor1 -> `1 - self.smfactor`
112 | - movav = prev * (1.0 - smoothfactor) + newdata * smoothfactor
113 | :param data:
114 | :param period:
115 | :return:
116 | """
117 | end = len(data)
118 | if not self.inited:
119 | if end < period:
120 | return
121 | else:
122 | self.inited = True
123 | self.ema_data = deepcopy(data)
124 | close_line = data
125 | self.alpha = alpha
126 | if self.alpha is None:
127 | self.alpha = 2.0 / (1.0 + period)
128 | self.alpha1 = 1.0 - self.alpha
129 | prev = close_line[period-1]
130 | for i in range(period, end):
131 | self.ema_data[i] = prev = prev * self.alpha1 + close_line[i] * self.alpha
132 | return self.ema_data
133 |
134 | @getAverageName
135 | def wma(self, data:object, period=30):
136 | '''
137 | WeightedMovingAverage 加权移动平均线
138 | A Moving Average which gives an arithmetic weighting to values with the
139 | newest having the more weight
140 |
141 | Formula:
142 | - weights = range(1, period + 1)
143 | - coef = 2 / (period * (period + 1))
144 | - movav = coef * Sum(weight[i] * data[period - i] for i in range(period))
145 | '''
146 | end = len(data)
147 | if not self.inited:
148 | if end < period:
149 | return
150 | else:
151 | self.inited = True
152 | self.wma_data = deepcopy(data)
153 | close_line = data
154 | coef = 2.0 / (period * (period + 1.0))
155 | weights = tuple(float(x) for x in range(1, period + 1))
156 | for i in range(period, end):
157 | data = close_line[i - period + 1: i + 1]
158 | self.wma_data[i] = coef * math.fsum(map(operator.mul, data, weights))
159 | return self.wma_data
160 |
161 | @getIndicatorName
162 | def kd(self, data:object, period=14, period_dfast=3):
163 | """
164 | 随机振荡器 随机指标(KD) : K给出预期信号,以底部或之前的 D给出周转信号,以 D-Slow给出周转确认信号
165 | The regular (or slow version) adds an additional moving average layer and
166 | thus:
167 |
168 | - The percD line of the StochasticFast becomes the percK line
169 | - percD becomes a moving average of period_dslow of the original percD
170 |
171 | Formula:
172 | - hh = highest(data.high, period)
173 | - ll = lowest(data.low, period)
174 | - knum = data.close - ll
175 | - kden = hh - ll
176 | - k = 100 * (knum / kden)
177 | - d = MovingAverage(k, period_dfast)
178 |
179 | - d-slow = MovingAverage(d, period_dslow)
180 | See:
181 | - http://en.wikipedia.org/wiki/Stochastic_oscillator
182 | :param data:
183 | :param period:
184 | :return:
185 | """
186 | end = len(data)
187 | if not self.inited:
188 | period = max(period, period_dfast)
189 | if end < period:
190 | return
191 | else:
192 | self.inited = True
193 | highest = deepcopy(data)
194 | lowest = deepcopy(data)
195 | for i in range(period, end):
196 | highest[i] = max(self.ret_high[i - period + 1: i + 1])
197 | for i in range(period, end):
198 | lowest[i] = min(self.ret_low[i - period + 1: i + 1])
199 | knum = np.array(data) - lowest
200 | kden = np.array(highest) - np.array(lowest)
201 | self.k = 100 * (knum/kden)
202 | self.d = self.sma(self.k, period=period_dfast)
203 | self.percD = self.sma(self.d, period=period_dfast)
204 | return self.k, self.percD
205 |
206 | @getIndicatorName
207 | def macd(self, data:object, period_me1=12, period_me2=26, period_signal=9):
208 | """
209 | 移动平均趋同/偏离(异同移动平均线) MACDHisto
210 | Formula:
211 | - macd = ema(data, me1_period) - ema(data, me2_period)
212 | - signal = ema(macd, signal_period)
213 | - histo = macd - signal
214 | :param data:
215 | :param period:
216 | :return:
217 | """
218 | end = len(data)
219 | if not self.inited:
220 | period = max(period_me1, period_me2, period_signal)
221 | if end < period:
222 | return
223 | else:
224 | self.inited = True
225 | me1 = self.ema(data, period=period_me1)
226 | me2 = self.ema(data, period=period_me2)
227 | self.macds = np.array(me1) - np.array(me2)
228 | self.signal = self.ema(self.macds, period=period_signal)
229 | self.histo = np.array(self.macds) - np.array(self.signal)
230 | return self.macds, self.signal, self.histo
231 |
232 | @getAverageName
233 | def rsi(self, data:object, period=14, lookback=1):
234 | """
235 | rsi 相对强度指数
236 | Formula:
237 | - up = upday(data)
238 | - down = downday(data)
239 | - maup = sma(up, period) or ema(up, period)
240 | - madown = sma(down, period) or ema(down, period)
241 | - rs = maup / madown
242 | - rsi = 100 - 100 / (1 + rs)
243 | :param data:
244 | :param period:
245 | :return:
246 | """
247 | params = (
248 | ('period', 14),
249 | ('upperband', 70.0),
250 | ('lowerband', 30.0),
251 | ('safediv', False),
252 | ('safehigh', 100.0),
253 | ('safelow', 50.0),
254 | ('lookback', 1),
255 | )
256 | end = len(data)
257 | if not self.inited:
258 | if end < period:
259 | return
260 | else:
261 | self.inited = True
262 | upday = deepcopy(data)
263 | downday = deepcopy(data)
264 | for i in range(period, end):
265 | upday[i] = max(data[i]-data[i-1], 0.0)
266 | for i in range(period, end):
267 | downday[i] = max(data[i-1]-data[i], 0.0)
268 | maup = self.ema(upday, period=period)
269 | madown = self.ema(downday, period=period)
270 | rs = np.array(maup) / np.array(madown)
271 | self.rsi_list = []
272 | for i in rs:
273 | rsi = 100.0 - 100.0 / (1.0 + i)
274 | self.rsi_list.append(rsi)
275 | return self.rsi_list
276 |
277 | @getAverageName
278 | def smma(self, data:object, period:int, alpha=15):
279 | """
280 | smma 平滑移动平均值
281 | SmoothedMovingAverage
282 | :param data:
283 | :param period:
284 | :return:
285 | """
286 | end = len(data)
287 | if not self.inited:
288 | period = max(period, alpha)
289 | if end < period:
290 | return
291 | else:
292 | self.inited = True
293 | self.ema_data = deepcopy(data)
294 | close_line = data
295 | self.alpha = alpha
296 | if self.alpha is None:
297 | self.alpha = 2.0 / (1.0 + period)
298 | self.alpha1 = 1.0 - self.alpha
299 |
300 | prev = close_line[period - 1]
301 | for i in range(period, end):
302 | self.ema_data[i] = prev = prev * self.alpha1 + close_line[i] * self.alpha
303 | return self.ema_data
304 |
305 | @getIndicatorName
306 | def atr(self, data:object, period=14):
307 | """
308 | 平均真实范围
309 | AverageTrueRange
310 | :param data:
311 | :param period:
312 | :return:
313 | """
314 | end = len(data)
315 | if not self.inited:
316 | if end < period:
317 | return
318 | else:
319 | self.inited = True
320 | truehigh = []
321 | truelow = []
322 | truehigh = truehigh + [0] * period
323 | for h in range(period+1, end):
324 | truehigh.append(max(data[h-1], self.ret_high[h]))
325 | truelow = truelow + [0] * period
326 | for l in range(period+1, end):
327 | truelow.append(min(data[l-1], self.ret_low[l]))
328 | tr = np.array(truehigh) - np.array(truelow)
329 | atr = self.sma(tr, period=period)
330 | return atr
331 |
332 | @getIndicatorName
333 | def stdDev(self, data:object, period=20):
334 | """
335 | StandardDeviation 标准偏差 (StdDev) StandardDeviation
336 | If 2 datas are provided as parameters, the 2nd is considered to be the
337 | mean of the first
338 | Formula:
339 | - meansquared = SimpleMovingAverage(pow(data, 2), period) 均方
340 | - squaredmean = pow(SimpleMovingAverage(data, period), 2) 平方平均
341 | - stddev = pow(meansquared - squaredmean, 0.5) # square root
342 |
343 | See:
344 | - http://en.wikipedia.org/wiki/Standard_deviation
345 | :param data:
346 | :param period:
347 | :return:
348 | """
349 | end = len(data)
350 | if not self.inited:
351 | if end < period:
352 | return
353 | else:
354 | self.inited = True
355 | meansquared = self.sma(pow(np.array(data), 2), period)
356 | mead_data = self.sma(data, period)
357 | squaredmean = pow(mead_data, 2)
358 | self.stddev = pow(np.array(meansquared)-np.array(squaredmean), 0.5)
359 | return self.stddev
360 |
361 | @getAverageName
362 | def boll(self, data:object, period=20, devfactor=2):
363 | """
364 | 布林带 (BollingerBands boll 。中轨为股价的平均成本,上轨和下轨可分别视为股价的压力线和支撑线。)
365 | Formula:
366 | - midband = SimpleMovingAverage(close, period)
367 | - topband = midband + devfactor * StandardDeviation(data, period)
368 | - botband = midband - devfactor * StandardDeviation(data, period)
369 |
370 | See:
371 | - http://en.wikipedia.org/wiki/Bollinger_Bands
372 | :param data:
373 | :param period:
374 | :return: top mid bottom
375 | """
376 | end = len(data)
377 | if not self.inited:
378 | period = max(period, devfactor)
379 | if end < period:
380 | return
381 | else:
382 | self.inited = True
383 | self.mid = self.sma(data, period)
384 | self.top = np.array(self.mid) + devfactor * np.array(self.stdDev(data, period))
385 | self.bottom = np.array(self.mid) - devfactor * np.array(self.stdDev(data, period))
386 |
387 | return self.top, self.mid, self.bottom
388 |
389 | @getIndicatorName
390 | def AroonIndicator(self, data:object, period:int):
391 | """
392 | Formula:
393 | - up = 100 * (period - distance to highest high) / period
394 | - down = 100 * (period - distance to lowest low) / period
395 | See:
396 | - http://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:aroon
397 | :param data:
398 | :param period:
399 | :return:
400 | """
401 | pass
402 |
403 | @getAverageName
404 | def UltimateOscillator(self, data: object, period: int):
405 | '''
406 | 终极振荡器
407 | Formula:
408 | # Buying Pressure = Close - TrueLow
409 | BP = Close - Minimum(Low or Prior Close)
410 |
411 | # TrueRange = TrueHigh - TrueLow
412 | TR = Maximum(High or Prior Close) - Minimum(Low or Prior Close)
413 |
414 | Average7 = (7-period BP Sum) / (7-period TR Sum)
415 | Average14 = (14-period BP Sum) / (14-period TR Sum)
416 | Average28 = (28-period BP Sum) / (28-period TR Sum)
417 |
418 | UO = 100 x [(4 x Average7)+(2 x Average14)+Average28]/(4+2+1)
419 |
420 | See:
421 |
422 | - https://en.wikipedia.org/wiki/Ultimate_oscillator
423 | - http://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:ultimate_oscillator
424 | '''
425 | pass
426 |
427 | @getIndicatorName
428 | def trix(self, data: object, period: int, rocperiod=1):
429 | '''
430 | 三重指数平滑移动平均 技术分析(Triple Exponentially Smoothed Moving Average) TR
431 | Defined by Jack Hutson in the 80s and shows the Rate of Change (%) or slope
432 | of a triple exponentially smoothed moving average
433 |
434 | Formula:
435 | - ema1 = EMA(data, period)
436 | - ema2 = EMA(ema1, period)
437 | - ema3 = EMA(ema2, period)
438 | - trix = 100 * (ema3 - ema3(-1)) / ema3(-1)
439 |
440 | The final formula can be simplified to: 100 * (ema3 / ema3(-1) - 1)
441 |
442 | The moving average used is the one originally defined by Wilder,
443 | the SmoothedMovingAverage
444 |
445 | See:
446 | - https://en.wikipedia.org/wiki/Trix_(technical_analysis)
447 | - http://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:trix
448 | '''
449 | end = len(data)
450 | if not self.inited:
451 | if end < period:
452 | return
453 | else:
454 | self.inited = True
455 | ema1 = self.ema(data, period=period)
456 | ema2 = self.ema(ema1, period=period)
457 | ema3 = self.ema(ema2, period=period)
458 | end = len(ema3)
459 | self.trix_list = ema3
460 | for i in range(period, end):
461 | self.trix_list[i] = 100.0 * (ema3[i]/ema3[i-rocperiod] - 1.0)
462 | return self.trix_list
463 |
464 | @getIndicatorName
465 | def roc(self, data: object, period=12):
466 | """
467 | Formula:
468 | - roc = (data - data_period) / data_period
469 |
470 | See:
471 | - http://en.wikipedia.org/wiki/Momentum_(technical_analysis)
472 | :param data:
473 | :param period:
474 | :return:
475 | """
476 | end = len(data)
477 | if not self.inited:
478 | if end < period:
479 | return
480 | else:
481 | self.inited = True
482 | self.roc_list = deepcopy(data)
483 | for i in range(period, end):
484 | self.roc_list[i] = (data[i] - data[i-period]) / data[i-period]
485 | return self.roc_list
486 |
487 | @getIndicatorName
488 | def mtm(self, data: object, period: int):
489 | """
490 | 动量指标(MTM) Momentum
491 | Formula:
492 | - momentum = data - data_period
493 |
494 | See:
495 | - http://en.wikipedia.org/wiki/Momentum_(technical_analysis)
496 | :param data:
497 | :param period:
498 | :return:
499 | """
500 | end = len(data)
501 | if not self.inited:
502 | if end < period:
503 | return
504 | else:
505 | self.inited = True
506 | self.momentum_list = deepcopy(data)
507 | for i in range(period, end):
508 | self.momentum_list[i] = data[i] - data[i-period]
509 | return self.momentum_list
510 |
511 | @getIndicatorName
512 | def tema(self, data: object, period: int):
513 | """
514 | TripleExponentialMovingAverage(TEMA 试图减少与移动平均数相关的固有滞后)
515 | Formula:
516 | - ema1 = ema(data, period)
517 | - ema2 = ema(ema1, period)
518 | - ema3 = ema(ema2, period)
519 | - tema = 3 * ema1 - 3 * ema2 + ema3
520 | :param data:
521 | :param period:
522 | :return:
523 | """
524 | end = len(data)
525 | if not self.inited:
526 | if end < period:
527 | return
528 | else:
529 | self.inited = True
530 | ema1 = self.ema(data, period)
531 | ema2 = self.ema(ema1, period)
532 | ema3 = self.ema(ema2, period)
533 | self.tema_list = 3 * np.array(ema1) - 3 * ema2 + ema3
534 | return self.tema_list
535 |
536 | @getIndicatorName
537 | def wr(self, data:object, period=14):
538 | """
539 | WilliamsR
540 | Formula:
541 | - num = highest_period - close
542 | - den = highestg_period - lowest_period
543 | - percR = (num / den) * -100.0
544 |
545 | See:
546 | - http://en.wikipedia.org/wiki/Williams_%25R
547 | :param data:
548 | :param period:
549 | :return:
550 | """
551 | end = len(data)
552 | if not self.inited:
553 | if end < period:
554 | return
555 | else:
556 | self.inited = True
557 | num = deepcopy(data)
558 | den = deepcopy(data)
559 | for i in range(period, end):
560 | num[i] = max(self.ret_high[i - period + 1: i + 1])
561 | for i in range(period, end):
562 | den[i] = min(self.ret_low[i - period + 1: i + 1])
563 | self.percR = -100 * (np.array(num) / np.array(data)) / (np.array(num) - np.array(den))
564 | return self.percR
565 |
566 | def mean_dev(self, data, mean, period=20):
567 | """
568 | MeanDeviation
569 | Note:
570 | - If 2 datas are provided as parameters, the 2nd is considered to be the
571 | mean of the first
572 |
573 | Formula:
574 | - mean = MovingAverage(data, period) (or provided mean)
575 | - absdeviation = abs(data - mean)
576 | - meandev = MovingAverage(absdeviation, period)
577 |
578 | See:
579 | - https://en.wikipedia.org/wiki/Average_absolute_deviation
580 | :param data:
581 | :param period:
582 | :return:
583 | """
584 | absdev = abs(np.array(data)-np.array(mean))
585 | meandev = self.sma(absdev, period)
586 | return meandev
587 |
588 | def cci(self, period=20, factor=0.015):
589 | """
590 | 商品渠道指数 CommodityChannelIndex
591 | Formula:
592 | - tp = typical_price = (high + low + close) / 3
593 | - tpmean = MovingAverage(tp, period)
594 | - deviation = tp - tpmean
595 | - meandev = MeanDeviation(tp)
596 | - cci = deviation / (meandeviation * factor)
597 |
598 | See:
599 | - https://en.wikipedia.org/wiki/Commodity_channel_index
600 | :return:
601 | """
602 | end = len(self.ret_close)
603 | if not self.inited:
604 | if end < period:
605 | return
606 | else:
607 | self.inited = True
608 | tp = (self.ret_high + self.ret_low + self.ret_close) / 3
609 | tpmean = self.sma(tp, period)
610 | dev = np.array(tp) - np.array(tpmean)
611 | meandev = self.mean_dev(tp, tpmean, period)
612 | self.cci_list = np.array(dev) / (factor*meandev)
613 | return self.cci_list
614 |
615 | def sar(self, data, period=2, i_af=0.02, afmax=0.02):
616 | """
617 | 抛物线指标 Parabolic SAR
618 | See:
619 | - https://en.wikipedia.org/wiki/Parabolic_SAR
620 | - http://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:parabolic_sar
621 |
622 | :return:
623 | """
624 | self.sar_list = []
625 | status = {
626 | "sar": None,
627 | "tr": None,
628 | "af": 0.0,
629 | "ep": 0.0
630 | }
631 | num = len(data)
632 |
633 | sar = (self.ret_high[0] + self.ret_low[0]) / 2.0
634 | status['sar'] = sar
635 | status['af'] = i_af
636 | if data[1] >= data[0]:
637 | status['tr'] = False
638 | status['ep'] = self.ret_low[0]
639 | else:
640 | status['tr'] = True
641 | status['ep'] = self.ret_high[0]
642 |
643 | for i in range(num):
644 | n = i - period + 1
645 | m = n + 1
646 |
647 | hi = self.ret_high[m]
648 | lo = self.ret_low[m]
649 |
650 | tr = status['tr']
651 | sar = status['sar']
652 |
653 | if(tr and sar >= lo) or (not tr and sar <= hi):
654 | tr = not tr
655 | sar = status['ep']
656 | ep = hi if tr else lo
657 | af = i_af
658 | else:
659 | ep = status['ep']
660 | af = status['af']
661 |
662 | if tr:
663 | if hi > ep:
664 | ep = hi
665 | af = min(af + i_af, afmax)
666 | else:
667 | if lo < ep:
668 | ep = lo
669 | af = min(af + i_af, afmax)
670 | sar = sar + af * (ep - sar)
671 |
672 | if tr: # long trade
673 | lo1 = self.ret_low[n]
674 | if sar > lo or sar > lo1:
675 | sar = min(lo, lo1) # sar not above last 2 lows -> lower
676 | else:
677 | hi1 = self.ret_high[n]
678 | if sar < hi or sar < hi1:
679 | sar = max(hi, hi1)
680 | status['tr'] = tr
681 | status['sar'] = sar
682 | status['ep'] = ep
683 | status['af'] = af
684 | self.sar_list.append(status)
685 | return self.sar_list
--------------------------------------------------------------------------------
/indicator/interface.py:
--------------------------------------------------------------------------------
1 | from .plot import Scheduler
2 |
3 |
4 | class Indicator:
5 |
6 | @property
7 | def inited(self):
8 | """
9 | 用户判断是否满足计算指标
10 | :return: bool
11 | """
12 | return Scheduler.inited
13 |
14 | @property
15 | def open(self):
16 | """
17 | Get open price time series.
18 | """
19 | return Scheduler.ret_open
20 |
21 | @property
22 | def high(self):
23 | """
24 | Get high price time series.
25 | """
26 | return Scheduler.ret_high
27 |
28 | @property
29 | def low(self):
30 | """
31 | Get low price time series.
32 | """
33 | return Scheduler.ret_low
34 |
35 | @property
36 | def close(self):
37 | """
38 | Get low price time series
39 | :return:
40 | """
41 | return Scheduler.ret_close
42 |
43 | @property
44 | def volume(self):
45 | """
46 | Get volume number
47 | :return:
48 | """
49 | return Scheduler.ret_volume
50 |
51 | def open_csv(self, file: str, start_time=None, end_time=None):
52 | """
53 | open TXT file
54 | data_type:
55 | Date,Open,High,Low,Close,Volume
56 | '2019-01-07 00:00:00', 3831.0, 3847.0, 3831.0, 3840.0, 554
57 | '2019-01-08 00:00:00', 3841.0, 3841.0, 3833.0, 3836.0, 554
58 | ...
59 | :param file: name
60 | :param start_time:
61 | :param end_time:
62 | :return:
63 | """
64 | return Scheduler.open_csv(file, start_time, end_time)
65 |
66 | def open_json(self, file: str, start_time=None, end_time=None):
67 | """
68 | open JSON file
69 | data_type:
70 | {"zn1912.SHFE": [
71 | ["2014-01-01", 18780.0, 18780.0, 18770.0, 18775.0, 266],
72 | ["2014-01-02", 18775.0, 18780.0, 18770.0, 18770.0, 312],
73 | ...
74 | ]
75 | }
76 | :param file: name
77 | :param start_time:
78 | :param end_time:
79 | :return:
80 | """
81 | return Scheduler.open_json(file, start_time, end_time)
82 |
83 | def open_cache(self, data: list):
84 | """
85 | read CACHE data
86 | data_type:
87 | [["2014-01-01", 22, 44, 55, 55, 6666], ["2014-01-02", 22, 44, 55, 55, 6666], ...]
88 | :param data:
89 | :return:
90 | """
91 | return Scheduler.open_cache(data)
92 |
93 | def add_bar(self, data, opens=False):
94 | """
95 | new bar push in array
96 | :param data: bar
97 | :param opens: if True save file else not save (default False)
98 | :return:
99 | """
100 | Scheduler.update_bar(data, opens)
101 |
102 | def ma(self, n=15):
103 | if not self.inited:
104 | return
105 | data = Scheduler.ret_close
106 | return Scheduler.ma(data, n)
107 |
108 | def sma(self, n=15):
109 | data = Scheduler.ret_close
110 | return Scheduler.sma(data, n)
111 |
112 | def ema(self, n=12, alpha=None):
113 | data = Scheduler.ret_close
114 | return Scheduler.ema(data, n, alpha)
115 |
116 | def wma(self, n=30):
117 | data = Scheduler.ret_close
118 | return Scheduler.wma(data, n)
119 |
120 | def kd(self, n=14, f=3):
121 | data = Scheduler.ret_close
122 | return Scheduler.kd(data, n, f)
123 |
124 | def macd(self, n=12, m=20, f=9):
125 | data = Scheduler.ret_close
126 | return Scheduler.macd(data, n, m, f)
127 |
128 | def rsi(self, n=14, l=1):
129 | data = Scheduler.ret_close
130 | return Scheduler.rsi(data, n, l)
131 |
132 | def smma(self, n=10, alpha=15):
133 | data = Scheduler.ret_close
134 | return Scheduler.smma(data, n, alpha)
135 |
136 | def atr(self, n=14):
137 | data = Scheduler.ret_close
138 | return Scheduler.atr(data, n)
139 |
140 | def stdDev(self, n=20):
141 | data = Scheduler.ret_close
142 | return Scheduler.stdDev(data, n)
143 |
144 | def boll(self, n=20, m=2):
145 | data = Scheduler.ret_close
146 | return Scheduler.boll(data, n, m)
147 |
148 | def trix(self, n=15, m=1):
149 | data = Scheduler.ret_close
150 | return Scheduler.trix(data, n, m)
151 |
152 | def roc(self, n=12):
153 | data = Scheduler.ret_close
154 | return Scheduler.roc(data, n)
155 |
156 | def mtm(self, n=12):
157 | data = Scheduler.ret_close
158 | return Scheduler.mtm(data, n)
159 |
160 | def tema(self, n=25):
161 | data = Scheduler.ret_close
162 | return Scheduler.tema(data, n)
163 |
164 | def wr(self, n=14):
165 | data = Scheduler.ret_close
166 | return Scheduler.wr(data, n)
167 |
168 | def cci(self, n=20, f=0.015):
169 | return Scheduler.cci(n, f)
170 |
171 | def sar(self, n=2, af=0.02, afmax=0.20):
172 | data = Scheduler.ret_close
173 | return Scheduler.sar(data, n, af, afmax)
174 |
175 | def UltimateOscillator(self):
176 | pass
177 |
178 | def AroonIndicator(self):
179 | pass
180 |
181 | def plot(self, width=8, height=6, color="k", lw=0.5):
182 | Scheduler.plot(width=width, height=height, color=color, lw=lw)
183 |
184 |
185 | api = Indicator
--------------------------------------------------------------------------------
/indicator/json/zn1912.SHFE.json:
--------------------------------------------------------------------------------
1 | {"zn1912.SHFE": [
2 | ["2014-01-01", 18780.0, 18780.0, 18770.0, 18775.0, 266],
3 | ["2014-01-01", 18775.0, 18780.0, 18770.0, 18770.0, 312],
4 | ["2014-01-01", 18770.0, 18775.0, 18770.0, 18770.0, 172],
5 | ["2014-01-01", 18770.0, 18775.0, 18770.0, 18775.0, 78],
6 | ["2014-01-01", 18775.0, 18775.0, 18770.0, 18775.0, 88],
7 | ["2014-01-01", 18775.0, 18780.0, 18770.0, 18780.0, 224],
8 | ["2014-01-01", 18780.0, 18785.0, 18775.0, 18785.0, 294],
9 | ["2014-01-01", 18785.0, 18790.0, 18780.0, 18780.0, 422],
10 | ["2014-01-01", 18780.0, 18785.0, 18775.0, 18775.0, 376],
11 | ["2014-01-01", 18775.0, 18780.0, 18775.0, 18775.0, 118],
12 | ["2014-01-01", 18775.0, 18780.0, 18775.0, 18780.0, 24],
13 | ["2014-01-01", 18780.0, 18780.0, 18765.0, 18770.0, 442],
14 | ["2014-01-01", 18770.0, 18770.0, 18760.0, 18760.0, 360],
15 | ["2014-01-01", 18760.0, 18765.0, 18760.0, 18760.0, 484],
16 | ["2014-01-01", 18760.0, 18760.0, 18750.0, 18755.0, 498],
17 | ["2014-01-01", 18750.0, 18755.0, 18750.0, 18755.0, 352],
18 | ["2014-01-01", 18755.0, 18760.0, 18750.0, 18755.0, 342],
19 | ["2014-01-01", 18755.0, 18760.0, 18750.0, 18750.0, 128],
20 | ["2014-01-01", 18750.0, 18750.0, 18745.0, 18750.0, 424],
21 | ["2014-01-01", 18750.0, 18755.0, 18745.0, 18750.0, 256],
22 | ["2014-01-01", 18750.0, 18770.0, 18750.0, 18770.0, 750],
23 | ["2014-01-01", 18770.0, 18770.0, 18765.0, 18770.0, 84],
24 | ["2014-01-01", 18770.0, 18770.0, 18760.0, 18760.0, 154],
25 | ["2014-01-01", 18760.0, 18765.0, 18760.0, 18765.0, 26]
26 | ]}
--------------------------------------------------------------------------------
/indicator/plot.py:
--------------------------------------------------------------------------------
1 | """
2 | plot显示线
3 | """
4 | from .indicator import Indicator
5 |
6 | colors = {
7 | "sma": "b",
8 | "ema": "r",
9 | "wma": "c",
10 | "rsi": "g",
11 | "smma": "r",
12 | "atr": "w",
13 | "stddev": "k",
14 | "trix": "c",
15 | "mtm": "y",
16 | "tema": "m",
17 | "wr": "r",
18 | "macd": "g",
19 | "MACD": "r",
20 | "signal": "b",
21 | "K": "g",
22 | "D": "r",
23 | "mid": "g",
24 | "top": "r",
25 | "bottom": "b"
26 | }
27 |
28 |
29 | class ShowLine(Indicator):
30 | # def __new__(cls, *args, **kwargs):
31 | # if not hasattr(cls, "_instance"):
32 | # obj = super(ShowLine, cls)
33 | # cls._instance = obj.__new__(cls, *args, **kwargs)
34 | # return cls._instance
35 |
36 | def __init__(self):
37 | super().__init__()
38 |
39 | def plot(self, width=8, height=6, color="k", lw=0.5):
40 | try:
41 | from matplotlib import pyplot as plt
42 | from matplotlib.widgets import MultiCursor
43 | import matplotlib.dates as mdate
44 | except ImportError:
45 | raise ImportError("please pip install matplotlib")
46 | # 一个画布
47 | fig = plt.figure(figsize=(width, height))
48 | # 画布分块 块1
49 | ax1 = fig.add_subplot(211)
50 | datetime = self.ret_date
51 | volume = self.ret_volume
52 | close = self.ret_close
53 | # 柱
54 | ax1.bar(datetime, volume, color='y', label='volume')
55 | ax1.set_ylabel('volume')
56 | ax2 = ax1.twinx()
57 |
58 | # 线
59 | ax2.plot(datetime, close, "#000000", label="CLOSE")
60 | if self.average_message:
61 | for average_line in self.average_message:
62 | ax2.plot(datetime, self.average_message[average_line], colors[average_line], label=average_line)
63 |
64 | ax2.set_ylabel('price')
65 | # 标题
66 | plt.title("CTPBEE")
67 | # 网格
68 | plt.grid(True)
69 | # 图列
70 | plt.legend()
71 | # 显示时间间隔
72 | ax1.xaxis.set_major_formatter(mdate.DateFormatter('%Y-%m-%d %H:%M:%S'))
73 | # plt.xticks(pd.date_range(datetime[0], datetime[-1]))
74 |
75 | # 块2
76 | ax3 = plt.subplot(212)
77 | # 柱形图
78 | if self.indicator_message:
79 | for indicator_line in self.indicator_message:
80 | plt.plot(datetime, self.indicator_message[indicator_line], colors[indicator_line], label=indicator_line)
81 | # 网格
82 | plt.grid(True)
83 | plt.title("indicator")
84 | plt.legend()
85 | ax3.xaxis.set_major_formatter(mdate.DateFormatter('%Y-%m-%d %H:%M:%S')) # %H:%M:%S
86 | # plt.xticks(pd.date_range(datetime[0], datetime[-1]))
87 | multi = MultiCursor(fig.canvas, (ax1, ax3), color=color, lw=lw, useblit=True, linestyle=':', horizOn=True)
88 | plt.show()
89 |
90 |
91 | Scheduler = ShowLine()
--------------------------------------------------------------------------------
/indicator/readfile.py:
--------------------------------------------------------------------------------
1 | import os
2 | import sys
3 | import csv
4 | import json
5 | import time
6 | import numpy as np
7 | from datetime import datetime, date
8 |
9 |
10 | class ReadFile:
11 | def __init__(self):
12 | self.count = 0 # 数量
13 | self.ret_data = [] # 总数据
14 | self.ret_open = [] # 开盘价
15 | self.ret_low = [] # 最低价
16 | self.ret_high = [] # 最高价
17 | self.ret_date = [] # 时间
18 | self.ret_close = [] # 收盘价
19 | self.ret_volume = [] # 成交量
20 | self.open_file_name = None # 文件名
21 | self.open_file_start = None # 开始时间
22 | # self.inited = False # 是否满足计算要求
23 |
24 | def update_bar(self, datas: dict, switch=False):
25 | """
26 | :param data: 数据类型
27 | [time, open, high, low, close, volume]
28 | [1883823344, 22, 44, 55, 55, 6666]
29 | :param switch: 开关
30 | :return:
31 | """
32 | if not datas:
33 | raise Warning("type error or type is None")
34 | if isinstance(datas, dict):
35 | data = [datas["datetime"], datas["open_price"], datas["high_price"], datas["low_price"], datas["close_price"],
36 | 1]
37 | else:
38 | try:
39 | datas = datas._to_dict()
40 | except:
41 | raise TypeError("只支持 dict和BarData这个两种数据")
42 | data = [datas["datetime"], datas["open_price"], datas["high_price"], datas["low_price"],
43 | datas["close_price"],
44 | 1]
45 | if switch:
46 |
47 | if isinstance(data[0], datetime):
48 | data[0] = data[0].strftime('%Y-%m-%d %H:%M:%S')
49 | elif isinstance(data[0], date):
50 | data[0] = data[0].strftime('%Y-%m-%d')
51 | else:
52 | time_local = time.localtime(float(data[0]) / 1000)
53 | data[0] = time.strftime("%Y-%m-%d %H:%M:%S", time_local)
54 |
55 | if self.open_file_name.endswith(".csv"):
56 | with open(self.open_file_name, 'a+', newline='') as f:
57 | w_data = csv.writer(f)
58 | w_data.writerows(data)
59 | if self.open_file_name.endswith(".json"):
60 | with open(self.open_file_name, 'r') as jr:
61 | r_json = json.loads(jr.read())
62 | r_name = [name for name in r_json][0]
63 | r_json[r_name].append(data)
64 | with open(self.open_file_name, 'w') as jw:
65 | json.dump(r_json, jw)
66 |
67 | if self.open_file_name.endswith(".txt"):
68 | with open(self.open_file_name, 'a+') as t:
69 | txt = "\n" + str(data).strip("[]")
70 | t.write(txt)
71 |
72 | else:
73 | max_value = 60
74 | if self.count > max_value:
75 | self.ret_close = self.ret_close[-max_value:]
76 | self.ret_high = self.ret_high[-max_value:]
77 | self.ret_low = self.ret_low[-max_value:]
78 | self.ret_open = self.ret_open[-max_value:]
79 | self.ret_volume = self.ret_volume[-max_value:]
80 | self.count += 1
81 | # if not self.inited:
82 | # if self.count > 30:
83 | # self.inited = True
84 | self.ret_close = np.append(self.ret_close, data[4])
85 | self.ret_high = np.append(self.ret_high, data[2])
86 | self.ret_low = np.append(self.ret_low, data[3])
87 | self.ret_open = np.append(self.ret_open, data[1])
88 | self.ret_volume = np.append(self.ret_volume, data[5])
89 |
90 | def save_file(self, data):
91 | """保存数据"""
92 | pass
93 |
94 | def path(self, file):
95 | if not file:
96 | raise FileExistsError("文件名不能为空")
97 | modpath = os.path.dirname(os.path.abspath(sys.argv[0]))
98 | datapath = os.path.join(modpath, file)
99 | self.open_file_name = datapath
100 | return datapath
101 |
102 | def data_columns(self, data: str, start_time=None, end_time=None):
103 | self.ret_data = data
104 | self.ret_volume = data[4]
105 | self.ret_open = data[0]
106 | self.ret_low = data[2]
107 | self.ret_high = data[1]
108 | self.ret_close = data[3]
109 | self.count = len(data[4])
110 | return self.ret_close
111 |
112 | def open_csv(self, file: str, start_time=None, end_time=None):
113 | """
114 | 读取txt文件
115 | data_type:
116 | Date,Open,High,Low,Close,Volume
117 | '2019-01-07 00:00:00', 3831.0, 3847.0, 3831.0, 3840.0, 554
118 | '2019-01-08 00:00:00', 3841.0, 3841.0, 3833.0, 3836.0, 554
119 | ...
120 | :param file: 文件名
121 | :param start_time: 开始读取时间
122 | :param end_time: 结束时间
123 | :return: array对象
124 | """
125 | datapath = self.path(file)
126 | data = np.loadtxt(datapath, skiprows=2, dtype=float, delimiter=',', usecols=(1, 2, 3, 4, 5), unpack=True)
127 | ret_close = self.data_columns(data, start_time, end_time)
128 | return ret_close
129 |
130 | def open_json(self, file: str, start_time=None, end_time=None):
131 | """
132 | 读取json文件
133 | data_type:
134 | {"zn1912.SHFE": [
135 | ["2014-01-01", 18780.0, 18780.0, 18770.0, 18775.0, 266],
136 | ["2014-01-02", 18775.0, 18780.0, 18770.0, 18770.0, 312],
137 | ...
138 | ]
139 | }
140 | :param file: 文件名
141 | :param start_time:
142 | :param end_time:
143 | :return:
144 | """
145 | datapath = self.path(file)
146 | data_str = open(datapath).read()
147 | data_loads = json.loads(data_str)
148 | for data_name, data_all in data_loads.items():
149 | data_lines = data_all
150 | datas = np.array(data_lines)
151 | data = np.array([datas[:, 1], datas[:, 2], datas[:, 3], datas[:, 4], datas[:, 5]], dtype=float)
152 | ret_close = self.data_columns(data, start_time, end_time)
153 | return ret_close
154 |
155 | def open_cache(self, data:list):
156 | """
157 | 读取cache数据
158 | :param data:
159 | [[1883823344, 22, 44, 55, 55, 6666], [1883823345, 22, 44, 55, 55, 6666], ...]
160 | :return:
161 | """
162 | datas = np.array(data)
163 | data_array = np.array([datas[:, 1], datas[:, 2], datas[:, 3], datas[:, 4], datas[:, 5]], dtype=float)
164 | ret_close = self.data_columns(data_array)
165 | return ret_close
166 |
167 |
168 | File = ReadFile
169 |
--------------------------------------------------------------------------------
/test.py:
--------------------------------------------------------------------------------
1 | """
2 | 当前回测示例
3 | 1.当前数据基于rq进行下载的
4 | 2.首先你需要调用get_data 来获得rq的数据 ,然后save_to_json保存到 json文件中去,主要在此过程中你需要手动对数据加入symbol等
5 | 3.然后通过load_data函数重复调用数据
6 | 4.调用run_main进行回测
7 | 当前的strategy是借助vnpy的 ArrayManager . 你需要对此实现一些额外的安装操作
8 | 需要额外安装的包
9 | ta-lib, rqdatac( 后面需要被取代 ?? Maybe use quantdata )
10 | 目前暂时不够完善 ---> hope it will be a very fancy framework
11 | written by somewheve 2019-9-30 08:43
12 | """
13 |
14 | import json
15 | from datetime import datetime, date
16 | from ctpbee import LooperApi, Vessel
17 | from ctpbee.constant import Direction
18 | from indicator.interface import api
19 |
20 |
21 | def get_data(start, end, symbol, exchange, level):
22 | """ using rqdatac to make an example """
23 | # import rqdatac as rq
24 | # from rqdatac import get_price, id_convert
25 | # username = "license"
26 | # password = "NK-Ci7vnLsRiPPWYwxvvPYdYM90vxN60qUB5tVac2mQuvZ8f9Mq8K_nnUqVspOpi4BLTkSLgq8OQFpOOj7L" \
27 | # "t7AbdBZEBqRK74fIJH5vsaAfFQgl-tuB8l03axrW8cyN6-nBUho_6Y5VCRI63Mx_PN54nsQOpc1psIGEz" \
28 | # "gND8c6Y=bqMVlABkpSlrDNk4DgG-1QXNknJtk0Kkw2axvFDa0E_XPMqOcBxifuRa_DFI2svseXU-8A" \
29 | # "eLjchnTkeuvQkKh6nrfehVDiXjoMeq5sXgqpbgFAd4A5j2B1a0gpE3cb5kXb42n13fGwFaGris" \
30 | # "8-eKzz_jncvuAamkJEQQV0aLdiw="
31 | # host = "rqdatad-pro.ricequant.com"
32 | # port = 16011
33 | # rq.init(username, password, (host, port))
34 | # symbol_rq = id_convert(symbol)
35 | # data = get_price(symbol_rq, start_date=start, end_date=end, frequency=level, fields=None,
36 | # adjust_type='pre', skip_suspended=False, market='cn', expect_df=False)
37 | # origin = data.to_dict(orient='records')
38 | # result = []
39 | # for x in origin:
40 | # do = {}
41 | # do['open_price'] = x['open']
42 | # do['low_price'] = x['low']
43 | # do['high_price'] = x['high']
44 | # do['close_price'] = x['close']
45 | # do['datetime'] = datetime.strptime(str(x['trading_date']), "%Y-%m-%d %H:%M:%S")
46 | # do['symbol'] = symbol
47 | # do['local_symbol'] = symbol + "." + exchange
48 | # do['exchange'] = exchange
49 | # result.append(do)
50 | # return result
51 |
52 |
53 | def get_a_strategy():
54 |
55 | class SmaStrategy(LooperApi):
56 |
57 | def __init__(self, name):
58 | super().__init__(name)
59 | self.count = 1
60 | self.pos = 0
61 | self.bar_5 = api() # 5分钟bar线
62 | self.bar_3 = api() # 3分钟bar线
63 | self.bar_3.open_json('indicator/json/zn1912.SHFE.json') # 读取本地数据
64 | self.bar_5.open_json('indicator/json/zn1912.SHFE.json')
65 |
66 | self.allow_max_price = 5000 # 设置价格上限 当价格达到这个就卖出 防止突然跌
67 | self.allow_low_price = 2000 # 设置价格下限 当价格低出这里就卖 防止巨亏
68 |
69 | # self.bar_3.open_csv('indicator/txt/orcl-2014.txt')
70 |
71 | def on_bar(self, bar):
72 | # todo: 简单移动平均线
73 | """ """
74 | self.bar_3.add_bar(bar)
75 | # if not self.bar_3.inited:
76 | # return
77 | close = self.bar_3.close
78 | # 简单移动平均线
79 | # sma = self.bar_3.sma()
80 | # 加权移动
81 | # wma = self.bar_3.wma()
82 | # k d
83 | # k, d = self.bar_3.kd()
84 | # std
85 | # std = self.bar_3.bar_3.stdDev()
86 | # boll
87 | # t, m, b = self.bar_3.boll()
88 | # roc
89 | # roc = self.bar_3.roc()
90 | # mtm
91 | # mtm = self.bar_3.mtm()
92 | # wr
93 | # wr = self.bar_3.wr()
94 | # sar
95 | # sar = self.bar_3.sar()
96 | # macd
97 | macd, signal, histo = self.bar_3.macd()
98 | # rsi
99 | # rsi = self.bar_3.rsi()
100 | # atr
101 | # atr = self.bar_3.atr()
102 | # tema
103 | # tema = self.bar_3.tema()
104 | # ema
105 | # ema = self.bar_3.ema()
106 | # trix = self.bar_3.trix()
107 | # smma = self.bar_3.smma()
108 | # cci
109 | # cci = self.bar_3.cci()
110 |
111 | if self.allow_max_price < close[-1] and self.pos > 0:
112 | self.action.sell(bar.close_price, self.pos, bar)
113 |
114 | if self.allow_low_price > close[-1] and self.pos > 0:
115 | self.action.sell(bar.close_price, self.pos, bar)
116 |
117 | if histo[-1] > 0:
118 | if self.pos == 0:
119 | self.action.buy(bar.close_price, 1, bar)
120 | else:
121 | if self.pos > 0:
122 | self.action.sell(bar.close_price, 1, bar)
123 | self.action.short(bar.close_price, 1, bar)
124 |
125 | def on_trade(self, trade):
126 | if trade.direction == Direction.LONG:
127 | self.pos += trade.volume
128 | else:
129 | self.pos -= trade.volume
130 |
131 | def init_params(self, data):
132 | """"""
133 | # print("我在设置策略参数")
134 |
135 | class MacdStrategy(LooperApi):
136 | # todo: 简单异同移动平均 macd
137 | boll_window = 18
138 | boll_dev = 3.4
139 | cci_window = 10
140 | atr_window = 30
141 | sl_multiplier = 5.2
142 | fixed_size = 1
143 |
144 | boll_up = 0
145 | boll_down = 0
146 | cci_value = 0
147 | atr_value = 0
148 |
149 | intra_trade_high = 0
150 | intra_trade_low = 0
151 | long_stop = 0
152 | short_stop = 0
153 |
154 | parameters = ["boll_window", "boll_dev", "cci_window",
155 | "atr_window", "sl_multiplier", "fixed_size"]
156 | variables = ["boll_up", "boll_down", "cci_value", "atr_value",
157 | "intra_trade_high", "intra_trade_low", "long_stop", "short_stop"]
158 |
159 | def __init__(self, name):
160 | super().__init__(name)
161 | self.pos = 0
162 |
163 | def on_bar(self, bar):
164 | api.open_csv('indicator/txt/orcl-2014.txt')
165 | api.add_bar(bar, opens=True)
166 | close = api.close
167 | macd = api.macd()
168 | # 如果当前macd大于0就买
169 | if macd[-1] > 0:
170 | if self.pos == 0:
171 | pass
172 | elif self.pos > 0:
173 | self.action.cover(bar.close_price, 1, bar)
174 | self.action.buy(bar.close_price, 1, bar)
175 | # 如果小于就卖
176 | else:
177 | if self.pos > 0:
178 | self.action.sell(bar.close_price, 1, bar)
179 | self.action.short(bar.close_price, 1, bar)
180 |
181 | def on_trade(self, trade):
182 | if trade.direction == Direction.LONG:
183 | self.pos += trade.volume
184 | else:
185 | self.pos -= trade.volume
186 |
187 | def on_order(self, order):
188 | pass
189 |
190 | return SmaStrategy("double_ma")
191 | # return MacdStrategy("double_ma")
192 |
193 |
194 | def save_data_json(data):
195 | result = {"result": data}
196 |
197 | class CJsonEncoder(json.JSONEncoder):
198 | def default(self, obj):
199 | if isinstance(obj, datetime):
200 | return obj.strftime('%Y-%m-%d %H:%M:%S')
201 | elif isinstance(obj, date):
202 | return obj.strftime('%Y-%m-%d')
203 | else:
204 | return json.JSONEncoder.default(self, obj)
205 |
206 | with open("data.json", "w") as f:
207 | json.dump(result, f, cls=CJsonEncoder)
208 |
209 |
210 | def load_data():
211 | with open("data.json", "r") as f:
212 | data = json.load(f)
213 | return data.get("result")
214 |
215 |
216 | def run_main(data):
217 | vessel = Vessel()
218 | vessel.add_data(data)
219 | stra = get_a_strategy()
220 | vessel.add_strategy(stra)
221 | vessel.set_params({"looper":
222 | {"initial_capital": 100000,
223 | "commission": 0.005,
224 | "deal_pattern": "price",
225 | "size_map": {"ag1912.SHFE": 15},
226 | "today_commission": 0.005,
227 | "yesterday_commission": 0.02,
228 | "close_commission": 0.005,
229 | "slippage_sell": 0,
230 | "slippage_cover": 0,
231 | "slippage_buy": 0,
232 | "slippage_short": 0,
233 | "close_pattern": "yesterday",
234 | },
235 | "strategy": {}
236 | })
237 | vessel.run()
238 | from pprint import pprint
239 | result = vessel.get_result()
240 | pprint(result)
241 |
242 |
243 | if __name__ == '__main__':
244 | # data = get_data(start="2019-1-5", end="2019-9-1", symbol="ag1912", exchange="SHFE", level="15m")
245 | # save_data_json(data)
246 |
247 | data = load_data()
248 | for x in data:
249 | x['datetime'] = datetime.strptime(str(x['datetime']), "%Y-%m-%d %H:%M:%S")
250 | run_main(data)
251 |
252 |
--------------------------------------------------------------------------------
/zn1912.SHFE.json:
--------------------------------------------------------------------------------
1 | {"zn1912.SHFE": [
2 | ["2014-01-01", 18780.0, 18780.0, 18770.0, 18775.0, 266],
3 | ["2014-01-01", 18775.0, 18780.0, 18770.0, 18770.0, 312],
4 | ["2014-01-01", 18770.0, 18775.0, 18770.0, 18770.0, 172],
5 | ["2014-01-01", 18770.0, 18775.0, 18770.0, 18775.0, 78],
6 | ["2014-01-01", 18775.0, 18775.0, 18770.0, 18775.0, 88],
7 | ["2014-01-01", 18775.0, 18780.0, 18770.0, 18780.0, 224],
8 | ["2014-01-01", 18780.0, 18785.0, 18775.0, 18785.0, 294],
9 | ["2014-01-01", 18785.0, 18790.0, 18780.0, 18780.0, 422],
10 | ["2014-01-01", 18780.0, 18785.0, 18775.0, 18775.0, 376],
11 | ["2014-01-01", 18775.0, 18780.0, 18775.0, 18775.0, 118],
12 | ["2014-01-01", 18775.0, 18780.0, 18775.0, 18780.0, 24],
13 | ["2014-01-01", 18780.0, 18780.0, 18765.0, 18770.0, 442],
14 | ["2014-01-01", 18770.0, 18770.0, 18760.0, 18760.0, 360],
15 | ["2014-01-01", 18760.0, 18765.0, 18760.0, 18760.0, 484],
16 | ["2014-01-01", 18760.0, 18760.0, 18750.0, 18755.0, 498],
17 | ["2014-01-01", 18750.0, 18755.0, 18750.0, 18755.0, 352],
18 | ["2014-01-01", 18755.0, 18760.0, 18750.0, 18755.0, 342],
19 | ["2014-01-01", 18755.0, 18760.0, 18750.0, 18750.0, 128],
20 | ["2014-01-01", 18750.0, 18750.0, 18745.0, 18750.0, 424],
21 | ["2014-01-01", 18750.0, 18755.0, 18745.0, 18750.0, 256],
22 | ["2014-01-01", 18750.0, 18770.0, 18750.0, 18770.0, 750],
23 | ["2014-01-01", 18770.0, 18770.0, 18765.0, 18770.0, 84],
24 | ["2014-01-01", 18770.0, 18770.0, 18760.0, 18760.0, 154],
25 | ["2014-01-01", 18760.0, 18765.0, 18760.0, 18765.0, 26]
26 | ]}
--------------------------------------------------------------------------------