hyperquant 0.1.0__py3-none-any.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.
hyperquant/logkit.py ADDED
@@ -0,0 +1,190 @@
1
+ import logging
2
+ import sys
3
+ import unicodedata
4
+ from datetime import datetime
5
+ from zoneinfo import ZoneInfo
6
+ from colorama import Fore, Style, init
7
+ import os
8
+ import traceback
9
+
10
+ init(autoreset=True)
11
+
12
+ # ====================================================================================================
13
+ # ** 添加ok的日志级别 **
14
+ # 给默认的logging模块,添加一个用于表达成功的级别
15
+ # ====================================================================================================
16
+ OK_LEVEL = 25
17
+ logging.addLevelName(OK_LEVEL, "OK")
18
+
19
+ def ok(self, message, *args, **kwargs):
20
+ if self.isEnabledFor(OK_LEVEL):
21
+ self._log(OK_LEVEL, message, args, **kwargs)
22
+
23
+ logging.Logger.ok = ok
24
+
25
+ # ====================================================================================================
26
+ # ** 辅助函数 **
27
+ # - get_display_width(): 获取文本的显示宽度,中文字符算作1.685个宽度单位,以尽量保持显示居中
28
+ # ====================================================================================================
29
+ def get_display_width(text: str) -> int:
30
+ width = 0
31
+ for char in text:
32
+ if unicodedata.east_asian_width(char) in ('F', 'W', 'A'):
33
+ width += 1.685
34
+ else:
35
+ width += 1
36
+ return int(width)
37
+
38
+ # ====================================================================================================
39
+ # ** 自定义Logger类封装所有功能 **
40
+ # ====================================================================================================
41
+ class Logger:
42
+ OK_LEVEL = 25
43
+ FORMATS = {
44
+ logging.DEBUG: ('', ''),
45
+ logging.INFO: (Fore.BLUE, "🔵 "),
46
+ logging.WARNING: (Fore.YELLOW, "🔔 "),
47
+ logging.ERROR: (Fore.RED, "❌ "),
48
+ logging.CRITICAL: (Fore.RED + Style.BRIGHT, "⭕ "),
49
+ OK_LEVEL: (Fore.GREEN, "✅ "),
50
+ }
51
+
52
+ def __init__(self, name='Log', show_time=False, use_color=True, timezone="Asia/Shanghai"):
53
+ # 设置日志级别
54
+ self.logger = logging.getLogger(name)
55
+ self.logger.setLevel(logging.DEBUG)
56
+ self.show_time = show_time
57
+ self.timezone = timezone # 新增时区配置
58
+
59
+ # 如果已存在 handlers,先清理
60
+ if self.logger.hasHandlers():
61
+ self.logger.handlers.clear()
62
+
63
+ # 控制台输出 handler
64
+ console_handler = MinConsoleHandler(sys.stdout)
65
+ console_handler.setFormatter(MinFormatter(use_color=use_color, show_time=show_time, timezone=timezone))
66
+ self.logger.addHandler(console_handler)
67
+
68
+ # 禁用传播到根日志记录器
69
+ self.logger.propagate = False
70
+
71
+ def divider(self, name='', sep='=', display_time=True):
72
+ """打印带时间戳的分割线"""
73
+ seperator_len = 72
74
+ now = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
75
+ middle = f' {name} {now} ' if display_time else f' {name} '
76
+ middle_width = get_display_width(middle)
77
+ decoration_count = max(4, (seperator_len - middle_width) // 2)
78
+ line = sep * decoration_count + middle + sep * decoration_count
79
+
80
+ if get_display_width(line) < seperator_len:
81
+ line += sep
82
+
83
+ self.logger.debug(line)
84
+
85
+ def get_logger(self):
86
+ """返回 logger 实例"""
87
+ return self.logger
88
+
89
+ # 为各个日志级别创建方法,便于编辑器提示
90
+ def ok(self, message, *args, **kwargs):
91
+ return self.logger.ok(message, *args, **kwargs)
92
+
93
+ def info(self, message, *args, **kwargs):
94
+ return self.logger.info(message, *args, **kwargs)
95
+
96
+ def debug(self, message, *args, **kwargs):
97
+ return self.logger.debug(message, *args, **kwargs)
98
+
99
+ def warning(self, message, *args, **kwargs):
100
+ return self.logger.warning(message, *args, **kwargs)
101
+
102
+ def error(self, message, *args, **kwargs):
103
+ return self.logger.error(message, *args, **kwargs)
104
+
105
+ def critical(self, message, *args, **kwargs):
106
+ return self.logger.critical(message, *args, **kwargs)
107
+
108
+ def exception(self, message, *args, **kwargs):
109
+ return self.logger.exception(message, *args, **kwargs)
110
+
111
+ class MinFormatter(logging.Formatter):
112
+ def __init__(self, use_color=True, show_time=False, timezone="Asia/Shanghai"):
113
+ super().__init__("%(message)s")
114
+ self.use_color = use_color
115
+ self.show_time = show_time
116
+ self.timezone = timezone # 新增时区配置
117
+
118
+ def format(self, record):
119
+ original_message = record.getMessage()
120
+
121
+ # 使用配置的时区
122
+ local_tz = ZoneInfo(self.timezone)
123
+ timestamp = f"[{datetime.now(local_tz).strftime('%Y-%m-%d %H:%M:%S')}] " if self.show_time else ""
124
+
125
+ if self.use_color:
126
+ color, prefix = Logger.FORMATS.get(record.levelno, ('', ''))
127
+ formatted_message = f"{timestamp}{color}{prefix}{original_message}{Style.RESET_ALL}"
128
+ else:
129
+ _, prefix = Logger.FORMATS.get(record.levelno, ('', ''))
130
+ formatted_message = f"{timestamp}{prefix}{original_message}"
131
+
132
+ # 添加异常信息
133
+ if record.exc_info:
134
+ exc_text = ''.join(traceback.format_exception(*record.exc_info))
135
+ formatted_message += f"\n{Fore.RED}{exc_text}{Style.RESET_ALL}" if self.use_color else f"\n{exc_text}"
136
+
137
+ return formatted_message
138
+
139
+ class MinConsoleHandler(logging.StreamHandler):
140
+ def emit(self, record):
141
+ if record.levelno == logging.DEBUG:
142
+ print(self.format(record), flush=True)
143
+ elif record.levelno == Logger.OK_LEVEL:
144
+ super().emit(record)
145
+ print()
146
+ else:
147
+ super().emit(record)
148
+
149
+ # ====================================================================================================
150
+ # ** 功能函数 **
151
+ # ====================================================================================================
152
+ def get_logger(name=None, file_path=None, show_time=False, use_color=True, timezone="Asia/Shanghai") -> Logger:
153
+ if name is None:
154
+ name = '_'
155
+ logger_instance = Logger(name, show_time, use_color, timezone) # 传递时区参数
156
+ if file_path:
157
+ # 如果目录不存在,创建目录
158
+ os.makedirs(os.path.dirname(file_path), exist_ok=True)
159
+ add_file_handler(logger_instance.get_logger(), file_path, show_time, timezone)
160
+ return logger_instance
161
+
162
+ def add_file_handler(logger: logging.Logger, path: str, show_time=False, timezone="Asia/Shanghai"):
163
+ # 添加文件日志输出,启用时间戳
164
+ file_handler = logging.FileHandler(path)
165
+ file_handler.setFormatter(MinFormatter(use_color=False, show_time=show_time, timezone=timezone)) # 传递时区参数
166
+ logger.addHandler(file_handler)
167
+
168
+ # ====================================================================================================
169
+ # ** 示例使用 **
170
+ # ====================================================================================================
171
+ if __name__ == '__main__':
172
+ # 获取日志对象
173
+ logger = get_logger('xx', 'logs/application.log', show_time=True, use_color=True) # This will use Logger
174
+
175
+ # 输出日志信息
176
+ logger.debug("调试信息,没有标记和颜色,等同于print")
177
+ logger.info("提示信息,蓝色的,可以记录一些中间结果")
178
+ logger.ok("完成提示,绿色的,通常表示成功和完成")
179
+ logger.warning("警告信息,黄色的,通常表示警告")
180
+ logger.error("错误信息,红色的,通常是报错的相关提示")
181
+ logger.critical("重要提示,深红色。通常是非常关键的信息")
182
+
183
+ # 使用 divider 方法
184
+ logger.divider("这是一个分割线", sep='*', display_time=True)
185
+
186
+ # 触发一个异常
187
+ try:
188
+ 1 / 0
189
+ except Exception:
190
+ logger.exception("捕获到一个异常,程序将继续运行。")
@@ -0,0 +1,153 @@
1
+ Metadata-Version: 2.4
2
+ Name: hyperquant
3
+ Version: 0.1.0
4
+ Summary: A minimal yet hyper-efficient backtesting framework for quantitative trading
5
+ Project-URL: Homepage, https://github.com/yourusername/hyperquant
6
+ Project-URL: Issues, https://github.com/yourusername/hyperquant/issues
7
+ Author-email: MissinA <1421329142@qq.com>
8
+ License: MIT
9
+ Keywords: backtesting,hyperquant,quant,trading
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Topic :: Office/Business :: Financial :: Investment
15
+ Requires-Python: >=3.8
16
+ Requires-Dist: colorama>=0.4.6
17
+ Requires-Dist: pandas>=2.2.3
18
+ Requires-Dist: pyecharts>=2.0.8
19
+ Description-Content-Type: text/markdown
20
+
21
+ # minquant
22
+
23
+ minquant is a minimalistic framework for quantitative trading strategies. It allows users to quickly validate their strategy ideas with ease and efficiency.
24
+
25
+ ## Core APIs
26
+
27
+ ### `core.py`
28
+ 主要功能包括:
29
+ - `ExchangeBase` 和 `Exchange` 类:实现基础的交易功能
30
+ - 资产管理(初始资金、已实现/未实现盈亏等)
31
+ - 下单交易(买入、卖出、平仓等)
32
+ - 仓位管理和风控
33
+ - 账户状态更新和记录
34
+ - `gen_back_time` 函数:回测时间周期管理,支持训练和测试时间区间的生成
35
+
36
+ ### `draw.py`
37
+ 主要功能包括:
38
+ - 支持多种图表类型:K线、曲线、柱状图等
39
+ - 提供丰富的交互功能:
40
+ - 时间轴缩放和跳转
41
+ - 自动播放功能
42
+ - 多图表联动显示
43
+ - 指标叠加功能
44
+ - 提供详细的数据标注:
45
+ - 交易信号标记
46
+ - 数据显示和提示
47
+ - 自定义颜色和样式
48
+
49
+ ### `logkit.py`
50
+ 主要功能包括:
51
+ - 自定义日志级别和格式化:
52
+ - DEBUG: 调试信息
53
+ - INFO: 普通信息(蓝色)
54
+ - OK: 成功信息(绿色)
55
+ - WARNING: 警告信息(黄色)
56
+ - ERROR: 错误信息(红色)
57
+ - CRITICAL: 严重错误(深红色)
58
+ - 支持多种日志输出:
59
+ - 控制台彩色输出
60
+ - 文件日志记录
61
+ - 提供便捷的日志分割线和时间戳功能
62
+ - 支持异常信息的格式化输出
63
+ - 可配置时区和时间显示
64
+
65
+ ## 使用方法
66
+
67
+ ### 1. 初始化交易环境
68
+ ```python
69
+ from core import Exchange
70
+ # 创建交易实例,设置初始资金和交易品种
71
+ exchange = Exchange(
72
+ trade_symbols=['BTCUSDT'], # 交易品种
73
+ initial_balance=10000, # 初始资金
74
+ fee=0.0002, # 手续费率
75
+ recorded=True # 是否记录交易历史
76
+ )
77
+ ```
78
+
79
+ ### 2. 执行交易操作
80
+ ```python
81
+ # 买入操作
82
+ exchange.Buy('BTCUSDT', price=30000, amount=0.1, time='2024-01-01')
83
+
84
+ # 卖出操作
85
+ exchange.Sell('BTCUSDT', price=31000, amount=0.1, time='2024-01-02')
86
+
87
+ # 获取账户状态
88
+ print(exchange.stats)
89
+ ```
90
+
91
+ ### 3. 绘制分析图表
92
+ ```python
93
+ from draw import draw
94
+ import pandas as pd
95
+
96
+ # 准备数据
97
+ data_df = pd.DataFrame({
98
+ 'date': [...], # 时间列
99
+ 'open': [...], # 开盘价
100
+ 'close': [...], # 收盘价
101
+ 'high': [...], # 最高价
102
+ 'low': [...], # 最低价
103
+ 'volume': [...] # 成交量
104
+ })
105
+
106
+ # 配置图表
107
+ data_dict = [
108
+ {
109
+ 'series_name': 'K线图',
110
+ 'draw_type': 'Kline',
111
+ 'height': 60,
112
+ 'col': ['open', 'close', 'low', 'high']
113
+ },
114
+ {
115
+ 'series_name': '成交量',
116
+ 'draw_type': 'Bar',
117
+ 'height': 20,
118
+ 'col': 'volume'
119
+ }
120
+ ]
121
+
122
+ # 绘制图表
123
+ draw(
124
+ df=data_df,
125
+ data_dict=data_dict,
126
+ date_col='date',
127
+ title='BTC/USDT'
128
+ )
129
+ ```
130
+
131
+ ### 4. 日志记录
132
+ ```python
133
+ from logkit import get_logger
134
+
135
+ # 创建日志实例
136
+ logger = get_logger(
137
+ name='strategy', # 日志名称
138
+ file_path='logs/strategy.log', # 日志文件路径
139
+ show_time=True, # 显示时间戳
140
+ use_color=True # 使用彩色输出
141
+ )
142
+
143
+ # 记录不同级别的日志
144
+ logger.debug("调试信息")
145
+ logger.info("普通信息")
146
+ logger.ok("成功信息")
147
+ logger.warning("警告信息")
148
+ logger.error("错误信息")
149
+ logger.critical("严重错误")
150
+
151
+ # 使用分割线
152
+ logger.divider("回测开始", sep='=', display_time=True)
153
+ ```
@@ -0,0 +1,7 @@
1
+ hyperquant/__init__.py,sha256=NRq3MhT7sETNAP-EQ0y5fYgzZl2eAmo9llun1lojYl0,84
2
+ hyperquant/core.py,sha256=wYCQw10_Nzx1KUJnkuO6IqksElOWXZ8xaKp38oJfphY,18838
3
+ hyperquant/draw.py,sha256=jweENVzf0nWHogzUliwJHI2PgbeQ3V2H749cMJ256k0,54614
4
+ hyperquant/logkit.py,sha256=WALpXpIA3Ywr5DxKKK3k5EKubZ2h-ISGfc5dUReQUBQ,7795
5
+ hyperquant-0.1.0.dist-info/METADATA,sha256=jfV05dHrbYj4rldc1gM9c-IkW5BISCpOqRT3ToUtWNo,4161
6
+ hyperquant-0.1.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
7
+ hyperquant-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.27.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any