Skip to content

添加回测、模拟和实盘交易功能 #502

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

easonxu77
Copy link

@easonxu77 easonxu77 commented Mar 6, 2025

Summary by CodeRabbit

  • 新功能
    • 引入全新的交易运行功能,支持回测、模拟和实盘三种模式。
    • 提供直观的用户交互界面,指导用户选择合适的交易模式,并针对无效选择给予友好提示。

Copy link

coderabbitai bot commented Mar 6, 2025

📝 Walkthrough

Walkthrough

新增了一个 Python 脚本 example_run.py,提供三种交易模式的执行功能:回测、模拟交易和实盘交易。脚本内定义了 run_backtestrun_simulationrun_real_trading 三个函数分别对应不同交易模式,同时包含一个 main 函数用于接收用户输入并调用相应函数。其中,回测模式设置了日期范围,模拟交易设置了初始余额,实盘交易则配置了账户凭证,并对无效输入进行了错误处理。

Changes

文件 更改摘要
example_run.py 新增函数 run_backtestrun_simulationrun_real_tradingmain,分别用于回测、模拟交易和实盘交易。

Sequence Diagram(s)

sequenceDiagram
    participant 用户 as 用户
    participant Main as main()
    participant API as TqApi

    用户->>Main: 启动程序并选择交易模式
    alt 回测模式
        Main->>API: 调用 run_backtest() 初始化回测环境
    else 模拟模式
        Main->>API: 调用 run_simulation() 初始化模拟环境
    else 实盘模式
        Main->>API: 调用 run_real_trading() 初始化实盘环境
    end
Loading

Poem

我是一只小兔子,跳跃在代码的花园,
新增脚本展新容,回测与模拟轻松玩,
实盘交易展锋芒,
输入选择决策忙,
编程如诗愿幸运,交易路上笑声甜!

Warning

Review ran into problems

🔥 Problems

Errors were encountered while retrieving linked issues.

Errors (1)
  • JIRA integration encountered authorization issues. Please disconnect and reconnect the integration in the CodeRabbit UI.
✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (2)
example_run.py (2)

1-3: 导入部分结构良好,但可以考虑更加明确的导入方式

代码导入了所需的模块,包括date和多个tqsdk类。但为了更好的代码可读性和维护性,建议考虑使用更明确的导入语句。

-from datetime import date
-from tqsdk import TqApi, TqSim, TqAccount, TqBacktest, TqAuth
+from datetime import date
+from tqsdk import TqApi, TqSim, TqAccount, TqBacktest, TqAuth
+import logging  # 添加日志支持

25-27: 脚本入口点

脚本入口点的结构正确,但缺少一些基本的启动设置。

 if __name__ == "__main__":
+    # 设置基本日志配置
+    import os
+    import logging
+    logging.basicConfig(
+        level=logging.INFO,
+        format='%(asctime)s - %(levelname)s - %(message)s'
+    )
+    
+    # 检查是否有必要的环境变量
+    required_vars = ["TQ_USERNAME", "TQ_PASSWORD"]
+    missing = [var for var in required_vars if not os.environ.get(var)]
+    if missing:
+        print(f"警告: 缺少必要的环境变量: {', '.join(missing)}")
+        print("请设置这些环境变量或在代码中提供这些值")
+    
     main()
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 99411cd and fca9996.

📒 Files selected for processing (1)
  • example_run.py (1 hunks)
🧰 Additional context used
🪛 Ruff (0.8.2)
example_run.py

5-5: Local variable api is assigned to but never used

Remove assignment to unused variable api

(F841)


8-8: Local variable api is assigned to but never used

Remove assignment to unused variable api

(F841)


11-11: Local variable api is assigned to but never used

Remove assignment to unused variable api

(F841)

Comment on lines +13 to +24
def main():
print("请选择运行模式: 1. 回测 2. 模拟 3. 实盘")
choice = input("输入选择(1/2/3): ")
if choice == '1':
run_backtest()
elif choice == '2':
run_simulation()
elif choice == '3':
run_real_trading()
else:
print("无效选择,请输入1, 2或3")

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

主函数需要增强错误处理和用户体验

主函数实现了基本功能,但缺乏适当的异常处理和用户体验优化。

建议修改为:

 def main():
-    print("请选择运行模式: 1. 回测 2. 模拟 3. 实盘")
-    choice = input("输入选择(1/2/3): ")
-    if choice == '1':
-        run_backtest()
-    elif choice == '2':
-        run_simulation()
-    elif choice == '3':
-        run_real_trading()
-    else:
-        print("无效选择,请输入1, 2或3")
+    print("===============================")
+    print("交易系统 v1.0")
+    print("===============================")
+    print("请选择运行模式:")
+    print("1. 回测 - 使用历史数据测试策略")
+    print("2. 模拟 - 使用实时行情进行模拟交易")
+    print("3. 实盘 - 使用实际资金进行交易")
+    print("4. 退出")
+    print("===============================")
+    try:
+        choice = input("请输入选择(1/2/3/4): ")
+        if choice == '1':
+            run_backtest()
+        elif choice == '2':
+            run_simulation()
+        elif choice == '3':
+            confirm = input("确认要进行实盘交易吗?(y/n): ")
+            if confirm.lower() == 'y':
+                run_real_trading()
+            else:
+                print("已取消实盘交易")
+                main()  # 返回主菜单
+        elif choice == '4':
+            print("感谢使用,再见!")
+            return
+        else:
+            print("无效选择,请输入1, 2, 3或4")
+            main()  # 重新显示主菜单
+    except KeyboardInterrupt:
+        print("\n程序已被用户中断")
+    except Exception as e:
+        print(f"发生错误: {e}")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def main():
print("请选择运行模式: 1. 回测 2. 模拟 3. 实盘")
choice = input("输入选择(1/2/3): ")
if choice == '1':
run_backtest()
elif choice == '2':
run_simulation()
elif choice == '3':
run_real_trading()
else:
print("无效选择,请输入1, 2或3")
def main():
print("===============================")
print("交易系统 v1.0")
print("===============================")
print("请选择运行模式:")
print("1. 回测 - 使用历史数据测试策略")
print("2. 模拟 - 使用实时行情进行模拟交易")
print("3. 实盘 - 使用实际资金进行交易")
print("4. 退出")
print("===============================")
try:
choice = input("请输入选择(1/2/3/4): ")
if choice == '1':
run_backtest()
elif choice == '2':
run_simulation()
elif choice == '3':
confirm = input("确认要进行实盘交易吗?(y/n): ")
if confirm.lower() == 'y':
run_real_trading()
else:
print("已取消实盘交易")
main() # 返回主菜单
elif choice == '4':
print("感谢使用,再见!")
return
else:
print("无效选择,请输入1, 2, 3或4")
main() # 重新显示主菜单
except KeyboardInterrupt:
print("\n程序已被用户中断")
except Exception as e:
print(f"发生错误: {e}")

Comment on lines +4 to +6
def run_backtest():
api = TqApi(backtest=TqBacktest(start_dt=date(2021, 1, 1), end_dt=date(2021, 12, 31)), web_gui=True, auth=TqAuth("13760685574", "xdy19870920"))

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

认证凭据硬编码及未使用的变量问题

这段代码存在几个问题:

  1. 认证凭据直接硬编码在代码中,这是一个安全风险
  2. 创建的api变量从未被使用
  3. 缺少文档字符串说明函数用途
  4. 没有错误处理和资源清理

建议修改为:

-def run_backtest():
-    api = TqApi(backtest=TqBacktest(start_dt=date(2021, 1, 1), end_dt=date(2021, 12, 31)), web_gui=True, auth=TqAuth("13760685574", "xdy19870920"))
+def run_backtest():
+    """回测交易模式,使用2021年全年数据进行回测"""
+    try:
+        # 从环境变量或配置文件获取凭据
+        username = os.environ.get("TQ_USERNAME")
+        password = os.environ.get("TQ_PASSWORD")
+        
+        api = TqApi(backtest=TqBacktest(start_dt=date(2021, 1, 1), end_dt=date(2021, 12, 31)), 
+                   web_gui=True, 
+                   auth=TqAuth(username, password))
+        
+        # 这里添加您的交易策略代码
+        
+        # 等待策略运行
+        while True:
+            api.wait_update()
+    except Exception as e:
+        logging.error(f"回测过程中出现错误: {e}")
+    finally:
+        if api:
+            api.close()
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def run_backtest():
api = TqApi(backtest=TqBacktest(start_dt=date(2021, 1, 1), end_dt=date(2021, 12, 31)), web_gui=True, auth=TqAuth("13760685574", "xdy19870920"))
def run_backtest():
"""回测交易模式,使用2021年全年数据进行回测"""
try:
# 从环境变量或配置文件获取凭据
username = os.environ.get("TQ_USERNAME")
password = os.environ.get("TQ_PASSWORD")
api = TqApi(
backtest=TqBacktest(start_dt=date(2021, 1, 1), end_dt=date(2021, 12, 31)),
web_gui=True,
auth=TqAuth(username, password)
)
# 这里添加您的交易策略代码
# 等待策略运行
while True:
api.wait_update()
except Exception as e:
logging.error(f"回测过程中出现错误: {e}")
finally:
if api:
api.close()
🧰 Tools
🪛 Ruff (0.8.2)

5-5: Local variable api is assigned to but never used

Remove assignment to unused variable api

(F841)

Comment on lines +10 to +12
def run_real_trading():
api = TqApi(TqAccount("期货公司", "账户", "密码"), web_gui=True, auth=TqAuth("13760685574", "xdy19870920"))

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

实盘交易函数使用了占位符账户信息且存在相同问题

实盘交易函数不仅存在与前两个函数相同的问题,还使用了明显的占位符账户信息。

建议修改为:

-def run_real_trading():
-    api = TqApi(TqAccount("期货公司", "账户", "密码"), web_gui=True, auth=TqAuth("13760685574", "xdy19870920"))
+def run_real_trading():
+    """实盘交易模式,使用真实账户进行交易"""
+    try:
+        # 从环境变量或配置文件获取凭据
+        username = os.environ.get("TQ_USERNAME")
+        password = os.environ.get("TQ_PASSWORD")
+        broker = os.environ.get("TQ_BROKER")
+        account = os.environ.get("TQ_ACCOUNT")
+        account_password = os.environ.get("TQ_ACCOUNT_PASSWORD")
+        
+        if not all([broker, account, account_password, username, password]):
+            print("请先设置环境变量: TQ_BROKER, TQ_ACCOUNT, TQ_ACCOUNT_PASSWORD, TQ_USERNAME, TQ_PASSWORD")
+            return
+            
+        api = TqApi(TqAccount(broker, account, account_password), 
+                   web_gui=True, 
+                   auth=TqAuth(username, password))
+        
+        # 这里添加您的交易策略代码
+        
+        # 等待策略运行
+        while True:
+            api.wait_update()
+    except Exception as e:
+        logging.error(f"实盘交易过程中出现错误: {e}")
+    finally:
+        if api:
+            api.close()

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 Ruff (0.8.2)

11-11: Local variable api is assigned to but never used

Remove assignment to unused variable api

(F841)

Comment on lines +7 to +9
def run_simulation():
api = TqApi(TqSim(init_balance=100000), web_gui=True, auth=TqAuth("13760685574", "xdy19870920"))

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

模拟交易函数存在相同的安全和资源管理问题

与回测函数类似,模拟交易函数存在安全凭据硬编码和资源管理问题。

建议修改为:

-def run_simulation():
-    api = TqApi(TqSim(init_balance=100000), web_gui=True, auth=TqAuth("13760685574", "xdy19870920"))
+def run_simulation():
+    """模拟交易模式,初始资金为100000"""
+    try:
+        # 从环境变量或配置文件获取凭据
+        username = os.environ.get("TQ_USERNAME")
+        password = os.environ.get("TQ_PASSWORD")
+        
+        api = TqApi(TqSim(init_balance=100000), 
+                   web_gui=True, 
+                   auth=TqAuth(username, password))
+        
+        # 这里添加您的交易策略代码
+        
+        # 等待策略运行
+        while True:
+            api.wait_update()
+    except Exception as e:
+        logging.error(f"模拟交易过程中出现错误: {e}")
+    finally:
+        if api:
+            api.close()

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 Ruff (0.8.2)

8-8: Local variable api is assigned to but never used

Remove assignment to unused variable api

(F841)

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant