hikyuu 2.1.0__cp39-none-win_amd64.whl → 2.1.2__cp39-none-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. hikyuu/cpp/boost_date_time-mt.dll +0 -0
  2. hikyuu/cpp/boost_serialization-mt.dll +0 -0
  3. hikyuu/cpp/boost_wserialization-mt.dll +0 -0
  4. hikyuu/cpp/core39.pyd +0 -0
  5. hikyuu/cpp/hikyuu.dll +0 -0
  6. hikyuu/cpp/sqlite3.dll +0 -0
  7. hikyuu/examples/notebook/006-TradeManager.ipynb +41 -39
  8. hikyuu/examples/notebook/008-Pickle.ipynb +27 -35
  9. hikyuu/extend.py +3 -1
  10. hikyuu/fetcher/stock/zh_stock_a_qmt.py +49 -0
  11. hikyuu/gui/HikyuuTDX.py +13 -7
  12. hikyuu/gui/data/MainWindow.py +126 -126
  13. hikyuu/gui/spot_server.py +16 -7
  14. hikyuu/gui/start_qmt.py +36 -0
  15. hikyuu/include/hikyuu/DataType.h +2 -1
  16. hikyuu/include/hikyuu/KRecord.h +1 -1
  17. hikyuu/include/hikyuu/Stock.h +1 -1
  18. hikyuu/include/hikyuu/StockManager.h +3 -0
  19. hikyuu/include/hikyuu/StrategyContext.h +7 -2
  20. hikyuu/include/hikyuu/analysis/combinate.h +1 -1
  21. hikyuu/include/hikyuu/config.h +0 -12
  22. hikyuu/include/hikyuu/data_driver/base_info/table/HistoryFinanceTable.h +2 -2
  23. hikyuu/include/hikyuu/doc.h +2 -2
  24. hikyuu/include/hikyuu/global/GlobalSpotAgent.h +1 -0
  25. hikyuu/include/hikyuu/global/GlobalTaskGroup.h +4 -2
  26. hikyuu/include/hikyuu/global/SpotRecord.h +52 -0
  27. hikyuu/include/hikyuu/global/agent/SpotAgent.h +14 -41
  28. hikyuu/include/hikyuu/hikyuu.h +1 -0
  29. hikyuu/include/hikyuu/strategy/{AccountTradeManager.h → BrokerTradeManager.h} +97 -95
  30. hikyuu/include/hikyuu/strategy/RunPortfolioInStrategy.h +36 -0
  31. hikyuu/include/hikyuu/strategy/RunSystemInStrategy.h +37 -0
  32. hikyuu/include/hikyuu/strategy/Strategy.h +174 -0
  33. hikyuu/include/hikyuu/trade_manage/FundsRecord.h +8 -8
  34. hikyuu/include/hikyuu/trade_manage/OrderBrokerBase.h +66 -14
  35. hikyuu/include/hikyuu/trade_manage/PositionRecord.h +12 -12
  36. hikyuu/include/hikyuu/trade_manage/TradeManager.h +9 -0
  37. hikyuu/include/hikyuu/trade_manage/TradeManagerBase.h +19 -0
  38. hikyuu/include/hikyuu/utilities/FilterNode.h +267 -0
  39. hikyuu/include/hikyuu/utilities/LRUCache11.h +230 -0
  40. hikyuu/include/hikyuu/{Log.h → utilities/Log.h} +91 -113
  41. hikyuu/include/hikyuu/utilities/Null.h +1 -0
  42. hikyuu/include/hikyuu/utilities/Parameter.h +2 -1
  43. hikyuu/include/hikyuu/utilities/ResourcePool.h +636 -0
  44. hikyuu/include/hikyuu/utilities/SpendTimer.h +10 -9
  45. hikyuu/include/hikyuu/utilities/TimerManager.h +25 -11
  46. hikyuu/include/hikyuu/utilities/any_to_string.h +142 -0
  47. hikyuu/include/hikyuu/utilities/arithmetic.h +71 -35
  48. hikyuu/include/hikyuu/utilities/base64.h +59 -0
  49. hikyuu/include/hikyuu/utilities/config.h +41 -0
  50. hikyuu/include/hikyuu/utilities/datetime/Datetime.h +42 -31
  51. hikyuu/include/hikyuu/utilities/datetime/TimeDelta.h +24 -13
  52. hikyuu/include/hikyuu/utilities/db_connect/DBCondition.h +48 -48
  53. hikyuu/include/hikyuu/utilities/db_connect/DBConnect.h +10 -0
  54. hikyuu/include/hikyuu/utilities/db_connect/DBConnectBase.h +5 -22
  55. hikyuu/include/hikyuu/utilities/db_connect/DBUpgrade.h +3 -3
  56. hikyuu/include/hikyuu/utilities/db_connect/SQLException.h +1 -1
  57. hikyuu/include/hikyuu/utilities/db_connect/SQLResultSet.h +1 -1
  58. hikyuu/include/hikyuu/utilities/db_connect/SQLStatementBase.h +7 -7
  59. hikyuu/include/hikyuu/utilities/db_connect/TableMacro.h +1 -2
  60. hikyuu/include/hikyuu/utilities/db_connect/mysql/MySQLConnect.h +9 -9
  61. hikyuu/include/hikyuu/utilities/db_connect/mysql/MySQLStatement.h +18 -18
  62. hikyuu/include/hikyuu/utilities/db_connect/sqlite/SQLiteConnect.h +3 -3
  63. hikyuu/include/hikyuu/utilities/db_connect/sqlite/SQLiteStatement.h +2 -2
  64. hikyuu/include/hikyuu/utilities/db_connect/sqlite/SQLiteUtil.h +6 -6
  65. hikyuu/include/hikyuu/{exception.h → utilities/exception.h} +15 -16
  66. hikyuu/include/hikyuu/utilities/http_client/HttpClient.h +229 -0
  67. hikyuu/include/hikyuu/utilities/http_client/nng_wrap.h +517 -0
  68. hikyuu/include/hikyuu/utilities/http_client/url.h +25 -0
  69. hikyuu/include/hikyuu/utilities/{IniParser.h → ini_parser/IniParser.h} +10 -5
  70. hikyuu/include/hikyuu/utilities/ini_parser/__init__.py +1 -0
  71. hikyuu/include/hikyuu/utilities/md5.h +41 -0
  72. hikyuu/include/hikyuu/utilities/mo/__init__.py +1 -0
  73. hikyuu/include/hikyuu/utilities/mo/mo.h +48 -0
  74. hikyuu/include/hikyuu/utilities/mo/moFileReader.h +836 -0
  75. hikyuu/include/hikyuu/{global → utilities}/node/NodeClient.h +25 -18
  76. hikyuu/include/hikyuu/{global → utilities}/node/NodeError.h +1 -1
  77. hikyuu/include/hikyuu/{global → utilities}/node/NodeMessage.h +3 -2
  78. hikyuu/include/hikyuu/utilities/node/NodeServer.h +246 -0
  79. hikyuu/include/hikyuu/utilities/node/__init__.py +1 -0
  80. hikyuu/include/hikyuu/utilities/os.h +16 -15
  81. hikyuu/include/hikyuu/utilities/snowflake.h +110 -0
  82. hikyuu/include/hikyuu/utilities/string_view.h +70 -0
  83. hikyuu/include/hikyuu/utilities/thread/MQStealThreadPool.h +3 -3
  84. hikyuu/include/hikyuu/utilities/thread/MQThreadPool.h +3 -3
  85. hikyuu/include/hikyuu/utilities/thread/StealThreadPool.h +3 -3
  86. hikyuu/include/hikyuu/utilities/thread/ThreadPool.h +3 -3
  87. hikyuu/include/hikyuu/version.h +4 -4
  88. hikyuu/interactive.py +42 -137
  89. hikyuu/sqlite3.dll +0 -0
  90. hikyuu/strategy/__init__.py +0 -1
  91. hikyuu/strategy/strategy_demo1.py +53 -0
  92. hikyuu/strategy/strategy_demo2.py +47 -0
  93. hikyuu/strategy/strategy_demo3.py +24 -0
  94. hikyuu/trade_manage/broker.py +27 -11
  95. hikyuu/trade_manage/broker_easytrader.py +52 -6
  96. hikyuu/trade_manage/broker_mail.py +17 -20
  97. hikyuu/vcruntime140.dll +0 -0
  98. hikyuu/vcruntime140_1.dll +0 -0
  99. hikyuu-2.1.2.dist-info/METADATA +115 -0
  100. {hikyuu-2.1.0.dist-info → hikyuu-2.1.2.dist-info}/RECORD +105 -79
  101. {hikyuu-2.1.0.dist-info → hikyuu-2.1.2.dist-info}/top_level.txt +4 -2
  102. hikyuu/README.rst +0 -79
  103. hikyuu/include/hikyuu/strategy/StrategyBase.h +0 -156
  104. hikyuu/strategy/demo/__init__.py +0 -3
  105. hikyuu/strategy/strategy.py +0 -27
  106. hikyuu-2.1.0.dist-info/METADATA +0 -126
  107. /hikyuu/include/hikyuu/{global/node → utilities/http_client}/__init__.py +0 -0
  108. {hikyuu-2.1.0.dist-info → hikyuu-2.1.2.dist-info}/LICENSE +0 -0
  109. {hikyuu-2.1.0.dist-info → hikyuu-2.1.2.dist-info}/WHEEL +0 -0
  110. {hikyuu-2.1.0.dist-info → hikyuu-2.1.2.dist-info}/entry_points.txt +0 -0
@@ -24,8 +24,8 @@
24
24
  #pragma GCC diagnostic ignored "-Wsign-compare"
25
25
  #endif
26
26
 
27
- #ifndef HKU_API
28
- #define HKU_API
27
+ #ifndef HKU_UTILS_API
28
+ #define HKU_UTILS_API
29
29
  #endif
30
30
 
31
31
  namespace hku {
@@ -39,7 +39,7 @@ namespace hku {
39
39
  #ifdef _MSC_VER
40
40
  class StealThreadPool {
41
41
  #else
42
- class HKU_API StealThreadPool {
42
+ class HKU_UTILS_API StealThreadPool {
43
43
  #endif
44
44
  public:
45
45
  /**
@@ -25,8 +25,8 @@
25
25
  #pragma GCC diagnostic ignored "-Wsign-compare"
26
26
  #endif
27
27
 
28
- #ifndef HKU_API
29
- #define HKU_API
28
+ #ifndef HKU_UTILS_API
29
+ #define HKU_UTILS_API
30
30
  #endif
31
31
 
32
32
  namespace hku {
@@ -40,7 +40,7 @@ namespace hku {
40
40
  #ifdef _MSC_VER
41
41
  class ThreadPool {
42
42
  #else
43
- class HKU_API ThreadPool {
43
+ class HKU_UTILS_API ThreadPool {
44
44
  #endif
45
45
  public:
46
46
  /**
@@ -12,13 +12,13 @@
12
12
  #define HKU_VERSION_H
13
13
 
14
14
  // clang-format off
15
- #define HKU_VERSION "2.1.0"
15
+ #define HKU_VERSION "2.1.2"
16
16
  #define HKU_VERSION_MAJOR 2
17
17
  #define HKU_VERSION_MINOR 1
18
- #define HKU_VERSION_ALTER 0
19
- #define HKU_VERSION_BUILD 202406180029
18
+ #define HKU_VERSION_ALTER 2
19
+ #define HKU_VERSION_BUILD 202408260144
20
20
  #define HKU_VERSION_MODE "RELEASE"
21
- #define HKU_VERSION_GIT "2.1.0 release.df43f718 (RELEASE)"
21
+ #define HKU_VERSION_GIT "2.1.2 release.619f2a88 (RELEASE)"
22
22
  // clang-format on
23
23
 
24
24
  #endif /* HKU_VERSION_H */
hikyuu/interactive.py CHANGED
@@ -255,44 +255,6 @@ def select(cond, start=Datetime(201801010000), end=Datetime.now(), print_out=Tru
255
255
  # ==============================================================================
256
256
 
257
257
 
258
- def UpdateOneRealtimeRecord_from_sina(tmpstr):
259
- try:
260
- if len(tmpstr) > 3 and tmpstr[:3] == 'var':
261
- a = tmpstr.split(',')
262
- if len(a) < 9:
263
- return
264
-
265
- open, close, high, low = float(a[1]), float(a[3]), float(a[4]), float(a[5])
266
- transamount = float(a[9])
267
- transcount = float(a[8])
268
-
269
- try:
270
- d = Datetime(a[-3])
271
- except:
272
- d = Datetime(a[-4])
273
- temp = (open, high, low, close)
274
- if 0 in temp:
275
- return
276
-
277
- stockstr = a[0].split('=')
278
- stock = sm[stockstr[0][-8:]]
279
-
280
- record = KRecord()
281
- record.datetime = d
282
- record.open = open
283
- record.high = high
284
- record.low = low
285
- record.close = close
286
- record.amount = transamount
287
- record.volume = transcount / 100
288
-
289
- stock.realtime_update(record)
290
-
291
- except Exception as e:
292
- print(tmpstr)
293
- print(e)
294
-
295
-
296
258
  def UpdateOneRealtimeRecord_from_qq(tmpstr):
297
259
  try:
298
260
  if len(tmpstr) > 3 and tmpstr[:2] == 'v_':
@@ -328,20 +290,6 @@ def UpdateOneRealtimeRecord_from_qq(tmpstr):
328
290
  print(e)
329
291
 
330
292
 
331
- def realtimePartUpdate_from_sina(queryStr):
332
- result = urllib.request.urlopen(queryStr).read()
333
- try:
334
- result = result.decode('gbk')
335
- except Exception as e:
336
- print(result)
337
- print(e)
338
- return
339
-
340
- result = result.split('\n')
341
- for tmpstr in result:
342
- UpdateOneRealtimeRecord_from_sina(tmpstr)
343
-
344
-
345
293
  def realtimePartUpdate_from_qq(queryStr):
346
294
  result = urllib.request.urlopen(queryStr).read()
347
295
  try:
@@ -356,14 +304,8 @@ def realtimePartUpdate_from_qq(queryStr):
356
304
  UpdateOneRealtimeRecord_from_qq(tmpstr)
357
305
 
358
306
 
359
- def realtime_update_from_sina_qq(source):
360
- if source == 'sina':
361
- hku_error("sina已不支持获取实时数据")
362
- return
363
- # queryStr = "http://hq.sinajs.cn/list="
364
- # update_func = realtimePartUpdate_from_sina
365
- # max_size = 140
366
- elif source == 'qq':
307
+ def realtime_update_from_website(source, stk_list=None):
308
+ if source == 'qq':
367
309
  queryStr = "http://qt.gtimg.cn/q="
368
310
  update_func = realtimePartUpdate_from_qq
369
311
  max_size = 60
@@ -374,7 +316,9 @@ def realtime_update_from_sina_qq(source):
374
316
  count = 0
375
317
  # urls = []
376
318
  tmpstr = queryStr
377
- for stock in sm:
319
+ if stk_list is None:
320
+ stk_list = sm
321
+ for stock in stk_list:
378
322
  if stock.valid and stock.type in (
379
323
  constant.STOCKTYPE_A, constant.STOCKTYPE_INDEX, constant.STOCKTYPE_ETF, constant.STOCKTYPE_GEM, constant.STOCKTYPE_A_BJ,
380
324
  ):
@@ -402,99 +346,60 @@ def realtime_update_from_sina_qq(source):
402
346
  # pool.join()
403
347
 
404
348
 
405
- def realtime_update_from_tushare():
406
- import tushare as ts
407
-
408
- # 更新股票行情
409
- df = ts.get_today_all()
410
- for i in range(len(df)):
411
- if df.ix[i, 'open'] == 0:
412
- continue # 停牌
413
-
414
- code = df.ix[i][0]
415
- stock = get_stock('sh' + code)
416
-
417
- if stock.isNull() == True or (stock.type != constant.STOCKTYPE_A and stock.type != constant.STOCKTYPE_A_BJ):
418
- stock = get_stock('sz' + code)
419
- if stock.isNull() == True:
420
- continue
421
-
422
- record = KRecord()
423
- record.open = df.ix[i, 'open']
424
- record.high = df.ix[i, 'high']
425
- record.lowe = df.ix[i, 'low']
426
- record.close = df.ix[i, 'trade']
427
- record.amount = float(df.ix[i, 'amount'])
428
- record.volume = float(df.ix[i, 'volume'])
429
-
430
- from datetime import date
431
- d = date.today()
432
- record.datetime = Datetime(d)
433
- stock.realtime_update(record)
434
-
435
- # 更新指数行情
436
- df = ts.get_index()
437
- for i in range(len(df)):
438
- code = df.ix[i][0]
439
- stock = get_stock('sh' + code)
440
- if stock.isNull() == True or stock.type != constant.STOCKTYPE_INDEX:
441
- stock = get_stock('sz' + code)
442
- if stock.isNull() == True:
443
- continue
444
-
445
- total = stock.getCount(Query.DAY)
446
- if total == 0:
447
- continue
448
-
449
- last_record = stock.getKRecord(total - 1)
450
-
451
- record = KRecord()
452
- record.open = df.ix[i, 'open']
453
- record.high = df.ix[i, 'high']
454
- record.low = df.ix[i, 'low']
455
- record.close = df.ix[i, 'close']
456
- record.volume = float(df.ix[i, 'volume'])
457
- record.amount = float(df.ix[i, 'amount'])
458
-
459
- if (
460
- last_record.close != record.close or last_record.high != record.high or last_record.low != record.low
461
- or last_record.open != record.open
462
- ):
463
- from datetime import date
464
- d = date.today()
465
- record.datetime = Datetime(d)
349
+ def realtime_update_from_qmt(stk_list=None):
350
+ from xtquant import xtdata
351
+ if stk_list is None:
352
+ stk_list = sm
353
+ code_list = [f'{s.code}.{s.market}' for s in stk_list if s.valid]
354
+ full_tick = xtdata.get_full_tick(code_list)
355
+ for qmt_code, data in full_tick.items():
356
+ try:
357
+ code, market = qmt_code.split(".")
358
+ stock = sm[f'{market}{code}']
359
+ record = KRecord()
360
+ record.datetime = Datetime(data['timetag'].split(' ')[0])
361
+ record.open = data['open']
362
+ record.high = data['high']
363
+ record.low = data['low']
364
+ record.close = data['lastPrice']
365
+ record.volume = data['volume'] * 0.1
366
+ record.amount = data['amount'] * 0.001
466
367
  stock.realtime_update(record)
368
+ except Exception as e:
369
+ hku_error(str(e))
370
+ except:
371
+ pass
467
372
 
468
373
 
469
- def realtime_update_inner(source='sina'):
470
- if source == 'sina' or source == 'qq':
471
- realtime_update_from_sina_qq(source)
472
- elif source == 'tushare':
473
- realtime_update_from_tushare()
374
+ def realtime_update_inner(source='qq', stk_list=None):
375
+ if source == 'qq':
376
+ realtime_update_from_website(source, stk_list)
377
+ elif source == 'qmt':
378
+ realtime_update_from_qmt(stk_list)
474
379
  else:
475
- print(source, ' not support!')
380
+ hku_error(f'Not support website source: {source}!')
476
381
 
477
382
 
478
383
  def realtime_update_wrap():
479
384
  pre_update_time = None
480
385
 
481
- def realtime_update_closure(source='qq', delta=60):
386
+ def realtime_update_closure(source='qq', delta=60, stk_list=None):
482
387
  """
483
388
  更新实时日线数据
484
- 参数:
485
- source: 数据源('sina' | 'qq' | 'tushare')
486
- delta: 更新间隔时间
389
+ :param str source: 数据源 ('qq' | 'qmt')
390
+ :param int delta: 最小更新间隔时间, 防止更新过于频繁
391
+ :param sequence stk_list: 待更新的stock列表, 如为 None 则更新全部
487
392
  """
488
393
  from datetime import timedelta, datetime
489
394
  nonlocal pre_update_time
490
395
  now_update_time = datetime.now()
491
- if (pre_update_time is None) or (now_update_time - pre_update_time) > timedelta(0, delta, 0):
492
- realtime_update_inner(source)
396
+ if (source == 'qmt') or (pre_update_time is None) or (now_update_time - pre_update_time) > timedelta(0, delta, 0):
397
+ realtime_update_inner(source, stk_list)
493
398
  pre_update_time = datetime.now()
494
- print("更新完毕!", pre_update_time)
399
+ print(f"更新完毕!更新时间: {pre_update_time}")
495
400
  else:
496
- print("更新间隔小于" + str(delta) + "秒,未更新")
497
- print("上次更新时间: ", pre_update_time)
401
+ print(f"更新间隔小于 {str(delta)} 秒,未更新")
402
+ print(f"上次更新时间: {pre_update_time}")
498
403
 
499
404
  return realtime_update_closure
500
405
 
hikyuu/sqlite3.dll ADDED
Binary file
@@ -1,3 +1,2 @@
1
1
  #!/usr/bin/python
2
2
  # -*- coding: utf8 -*-
3
- # cp936
@@ -0,0 +1,53 @@
1
+ #!/usr/bin/python
2
+ # -*- coding: utf8 -*-
3
+ # cp936
4
+
5
+ #
6
+ # 警告:Hikyuu 为量化研究工具,本身不包含程序化交易接口。此部分仅为策略调度运行时示例,
7
+ # 供自行实现程序化交易时参考,请自行负责程序化交易可能造成的损失。
8
+ #
9
+
10
+ from hikyuu import Strategy, Query, Datetime, Seconds, Minutes
11
+ from hikyuu import sm
12
+
13
+
14
+ def on_change(stk, spot):
15
+ print("[on_change]:", stk.market_code, stk.name, spot.close, spot.bid1, spot.ask1)
16
+
17
+
18
+ def on_spot(rev_time):
19
+ print("[on_received_spot] rev_time:", rev_time)
20
+
21
+
22
+ def my_func1():
23
+ print("[my_func1]", str(Datetime.now()))
24
+
25
+
26
+ def my_func2():
27
+ print("[my_func2] calculate:", Datetime.now())
28
+ for s in sm:
29
+ print(s)
30
+
31
+
32
+ # 注意:
33
+ # 1.每一个Strategy 只能作为独立进程执行,即 python xxx.py 的方式执行!
34
+ # 2.请开启 HikyuuTdx 行情采集,否则接收不到数据
35
+ # Strategy 方式运行示例
36
+ if __name__ == '__main__':
37
+ # 创建策略运行时,必须指定 stock 和 ktype 列表
38
+ # strategy 只会加载指定的 stock, ktype 的数据,行情接收也只会更新这些数据
39
+ # 如需使用交易日历,请记得同时指定 sh000001
40
+ s = Strategy(['sh600000', 'sz000001'], [Query.MIN, Query.DAY])
41
+
42
+ # 当前自动10秒后执行,忽略节假日限制
43
+ s.run_daily_at(my_func1, Datetime.now() - Datetime.today() + Seconds(10), False)
44
+
45
+ # 收到指定 stock 的行情更新
46
+ s.on_change(on_change)
47
+
48
+ # 收到行情更新
49
+ s.on_received_spot(on_spot)
50
+
51
+ # 每隔 1 分钟循环一次 (ignore_market 忽略开闭市时间限制, 否则仅在开盘期间执行)
52
+ s.run_daily(my_func2, Minutes(1)) # , ignore_market=True)
53
+ s.start()
@@ -0,0 +1,47 @@
1
+ #!/usr/bin/python
2
+ # -*- coding: utf8 -*-
3
+
4
+ import easytrader
5
+ from hikyuu import *
6
+
7
+ #
8
+ # 警告:Hikyuu 为量化研究工具,本身不包含程序化交易接口。此部分仅为策略调度运行时示例,
9
+ # 供自行实现程序化交易时参考,请自行负责程序化交易可能造成的损失。
10
+ #
11
+
12
+ # 创建 easytrade 订单代理(示例仅支持华泰)可自行参照 EasyTraderOrderBroker 修改
13
+ # buy|sell 中已屏蔽实际通过easytrade下单,防止调试误操作
14
+ user = easytrader.use('ht_client')
15
+ user.connect(r'D:\htwt\xiadan.exe')
16
+ easy_ob = EasyTraderOrderBroker(user)
17
+ broker = crtOB(easy_ob)
18
+
19
+ # 获取交易系统策略
20
+ # 目前 run_in_strategy 只支持非延迟交易,即收盘时立刻买入/卖出
21
+ sys = get_part("default.sys.趋势双均线")
22
+ sys.set_param("buy_delay", False)
23
+ sys.set_param("sell_delay", False)
24
+
25
+
26
+ # 执行策略主体
27
+ def my_func():
28
+ # 这里示例使用的是 TC_Zero() 零成本算法,但实际建议使用接近实际的成本算法
29
+ # 因为 sys 不依赖于成交单中的实际成本,而是使用成本算法预算需要买入的数量
30
+ run_in_strategy(sys, sm['sz000001'], Query(Datetime(20240101)), broker, TC_Zero())
31
+
32
+
33
+ # 注意:
34
+ # 1.每一个Strategy 只能作为独立进程执行,即 python xxx.py 的方式执行!
35
+ # 2.请开启 HikyuuTdx 行情采集,否则接收不到数据
36
+ # Strategy 方式运行示例
37
+ if __name__ == '__main__':
38
+ # 创建策略运行时,必须指定 stock 和 ktype 列表
39
+ # strategy 只会加载指定的 stock, ktype 的数据,行情接收也只会更新这些数据
40
+ # 如需使用交易日历,请记得同时指定 sh000001
41
+ s = Strategy(['sh000001', 'sz000001'], [Query.DAY])
42
+
43
+ # 每交易日 14点55分 执行
44
+ s.run_daily_at(my_func, TimeDelta(0, 14, 55))
45
+ s.start()
46
+
47
+ # 上述,也可以参见 strategy_demo3.py 中使用 crt_sys_strategy 快捷创建 strategy
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/python
2
+ # -*- coding: utf8 -*-
3
+
4
+ #
5
+ # 警告:Hikyuu 为量化研究工具,本身不包含程序化交易接口。此部分仅为策略调度运行时示例,
6
+ # 供自行实现程序化交易时参考,请自行负责程序化交易可能造成的损失。
7
+ #
8
+
9
+ if __name__ == '__main__':
10
+ import easytrader
11
+ from hikyuu import *
12
+
13
+ # 创建 easytrade 订单代理(示例仅支持华泰)可自行参照 EasyTraderOrderBroker 修改
14
+ user = easytrader.use('ht_client')
15
+ user.connect(r'D:\htwt\xiadan.exe')
16
+ easy_ob = EasyTraderOrderBroker(user)
17
+ broker = crtOB(easy_ob)
18
+
19
+ sys = get_part("default.sys.趋势双均线")
20
+
21
+ # 直接使用 sys 创建 strategy 示例,如果为日线,则自动每日 14点55分 执行
22
+ # 如果 query 为日线以下(分钟线、5分钟线)则自动按对应间隔(分钟、5分钟)循环执行
23
+ stg = crt_sys_strategy(sys, "sz000001", Query(Datetime(20240101), ktype=Query.DAY), broker, TC_Zero(), "demo3")
24
+ stg.start()
@@ -29,7 +29,9 @@
29
29
  # 1. 20170704, Added by fasiondog
30
30
  # ===============================================================================
31
31
 
32
+ import json
32
33
  from hikyuu import OrderBrokerBase
34
+ from hikyuu.util import hku_error
33
35
 
34
36
 
35
37
  class OrderBrokerWrap(OrderBrokerBase):
@@ -44,15 +46,29 @@ class OrderBrokerWrap(OrderBrokerBase):
44
46
  super(OrderBrokerWrap, self).__init__(name)
45
47
  self._broker = broker
46
48
 
47
- def _buy(self, datetime, market, code, price, num):
48
- """实现 OrderBrokerBase 的 _buy 接口"""
49
- self._broker.buy('{}{}'.format(market, code), price, num)
50
- return datetime
49
+ def _buy(self, datetime, market, code, price, num, stoploss, goal_price, part_from):
50
+ """
51
+ 实现 OrderBrokerBase _buy 接口
52
+ :param str market: 证券市场
53
+ :param str code: 证券代码
54
+ :param float price: 买入价格
55
+ :param int num: 买入数量
56
+ """
57
+ self._broker.buy(market, code, price, num, stoploss, goal_price, part_from)
51
58
 
52
- def _sell(self, datetime, market, code, price, num):
59
+ def _sell(self, datetime, market, code, price, num, stoploss, goal_price, part_from):
53
60
  """实现 OrderBrokerBase 的 _sell 接口"""
54
- self._broker.sell('{}{}'.format(market, code), price, num)
55
- return datetime
61
+ self._broker.sell(market, code, price, num, stoploss, goal_price, part_from)
62
+
63
+ def _get_asset_info(self):
64
+ try:
65
+ if hasattr(self._broker, "get_asset_info"):
66
+ ret = self._broker.get_asset_info()
67
+ return json.dumps(ret) if type(ret) == dict else str(ret)
68
+ return str()
69
+ except Exception as e:
70
+ hku_error(e)
71
+ return str()
56
72
 
57
73
 
58
74
  class TestOrderBroker:
@@ -61,11 +77,11 @@ class TestOrderBroker:
61
77
  def __init__(self):
62
78
  pass
63
79
 
64
- def buy(self, code, price, num):
65
- print("买入:%s %.3f %i" % (code, price, num))
80
+ def buy(self, market, code, price, num, stoploss, goal_price, part_from):
81
+ print(f"买入:{market}{code}, 价格: {price}, 数量: {num} 预期止损价: {stoploss}, 预期目标价: {goal_price}, 信号来源: {part_from}")
66
82
 
67
- def sell(self, code, price, num):
68
- print("卖出:%s %.3f %i" % (code, price, num))
83
+ def sell(self, market, code, price, num, stoploss, goal_price, part_from):
84
+ print(f"卖出:{market}{code}, 价格: {price}, 数量: {num}, 信号来源: {part_from}")
69
85
 
70
86
 
71
87
  def crtOB(broker, name="NO_NAME"):
@@ -4,14 +4,60 @@
4
4
  # Create on: 2024-01-30
5
5
  # Author: fasiondog
6
6
 
7
+ from hikyuu import Datetime, hku_info
8
+
9
+
7
10
  class EasyTraderOrderBroker:
11
+ '''
12
+ 使用华泰客户端实例
13
+ 注意:buy|sell 中已屏蔽实际通过easytrade下单,防止调试误操作,请自行根据需要打开
14
+ '''
15
+
8
16
  def __init__(self, user):
9
17
  self.user = user
18
+ self.buffer = {}
19
+
20
+ def buy(self, market, code, price, num, stoploss, goal_price, part_from):
21
+ # self.user.buy(code, price=price, amount=num)
22
+ market_code = f"{market}{code}"
23
+ print(f"计划买入:{market_code} {price} {num}")
24
+ self.buffer[market_code] = (num, stoploss, goal_price)
25
+
26
+ def sell(self, market, code, price, num, stoploss, goal_price, part_from):
27
+ # self.user.sell(code, price=price, amount=num)
28
+ market_code = f"{market}{code}"
29
+ print(f"计划卖出:{market_code} {price} {num}")
30
+ if market_code in self.buffer:
31
+ old_num = self.buffer[market_code][0]
32
+ if old_num == num:
33
+ self.buffer.pop(market_code)
34
+ else:
35
+ self.buffer[market_code] = (old_num - num, stoploss, goal_price)
36
+
37
+ def get_asset_info(self):
38
+ '''以下只适用于华泰'''
39
+ balance = self.user.balance
40
+ cash = balance['可用金额']
41
+
42
+ positions = []
43
+ for v in self.user.position:
44
+ if v["市场类别"] == "上海A":
45
+ market = "SH"
46
+ elif v["市场类别"] == "深圳A":
47
+ market = "SZ"
48
+ else:
49
+ hku_info(f"Ignored not supported market: {v['市场类别']}")
50
+ continue
10
51
 
11
- def buy(self, code, price, num):
12
- self.user.buy(code[2:], price=price, amount=num)
13
- print("买入:%s %.3f %i" % (code, price, num))
52
+ code = v["证券代码"]
53
+ market_code = f"{market}{code}"
54
+ if market_code in self.buffer:
55
+ stoploss, goal_price = self.buffer[market_code]
56
+ else:
57
+ stoploss, goal_price = 0.0, 0.0
58
+ positions.append(dict(market=market, code=code,
59
+ number=v['可用余额'], stoploss=stoploss, goal_price=goal_price, cost_price=v['成本价']))
14
60
 
15
- def sell(self, code, price, num):
16
- self.user.sell(code[2:], price=price, amount=num)
17
- print("卖出:%s %.3f %i" % (code, price, num))
61
+ ret = dict(datetime=str(Datetime.now()), cash=cash, positions=positions)
62
+ print(ret)
63
+ return ret
@@ -24,24 +24,25 @@
24
24
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25
25
  # SOFTWARE.
26
26
 
27
- #===============================================================================
27
+ # ===============================================================================
28
28
  # History
29
29
  # 1. 20170704, Added by fasiondog
30
- #===============================================================================
30
+ # ===============================================================================
31
31
 
32
32
  import smtplib
33
33
  from email.mime.text import MIMEText
34
34
  from email.header import Header
35
-
35
+
36
+
36
37
  class MailOrderBroker:
37
38
  """
38
39
  邮件订单代理
39
40
  """
40
-
41
+
41
42
  def __init__(self, host, sender, pwd, receivers):
42
43
  """
43
44
  邮件订单代理,执行买入/卖出操作时发送 Email
44
-
45
+
45
46
  :param str host: smtp服务器地址
46
47
  :param int port: smtp服务器端口
47
48
  :param str sender: 发件邮箱(既用户名)
@@ -52,10 +53,10 @@ class MailOrderBroker:
52
53
  self._pwd = pwd
53
54
  self._sender = sender
54
55
  self._receivers = receivers
55
-
56
+
56
57
  def _sendmail(self, title, msg):
57
58
  """发送邮件
58
-
59
+
59
60
  :param str title: 邮件标题
60
61
  :param str msg: 邮件内容
61
62
  """
@@ -70,35 +71,31 @@ class MailOrderBroker:
70
71
  smtpObj.connect(self._host, 25)
71
72
  smtpObj.login(self._sender, self._pwd)
72
73
  smtpObj.sendmail(self._sender, self._receivers, message.as_string())
73
-
74
-
75
- def buy(self, code, price, num):
74
+
75
+ def buy(self, market, code, price, num, stoploss, goal_price, part_from):
76
76
  """执行买入操作,向指定的邮箱发送邮件,格式如下::
77
-
77
+
78
78
  邮件标题:【Hkyuu提醒】买入 证券代码
79
79
  邮件内容:买入:证券代码,价格:买入的价格,数量:买入数量
80
-
80
+
81
81
  :param str code: 证券代码
82
82
  :param float price: 买入价格
83
83
  :param int num: 买入数量
84
84
  """
85
- action = "买入:{},价格:{},数量:{} ".format(code, price, num)
85
+ action = "买入:{}{},价格:{},数量:{} ".format(market, code, price, num)
86
86
  title = "【Hkyuu提醒】买入 {}".format(code)
87
87
  self._sendmail(title, action)
88
-
89
88
 
90
- def sell(self, code, price, num):
89
+ def sell(self, market, code, price, num, stoploss, goal_price, part_from):
91
90
  """执行卖出操作,向指定的邮箱发送邮件,格式如下::
92
-
91
+
93
92
  邮件标题:【Hkyuu提醒】卖出 证券代码
94
93
  邮件内容:卖出:证券代码,价格:卖出的价格,数量:卖出数量
95
-
94
+
96
95
  :param str code: 证券代码
97
96
  :param float price: 卖出价格
98
97
  :param int num: 卖出数量
99
98
  """
100
- title = "【Hkyuu提醒】卖出 {}".format(code)
99
+ title = "【Hkyuu提醒】卖出 {}{}".format(market, code)
101
100
  action = "卖出:{},价格:{},数量:{} ".format(code, price, num)
102
101
  self._sendmail(title, action)
103
-
104
-
Binary file
Binary file