redis - 远程发送买卖信号、本地接收信号处理

我们经常会有这样的场景:想在远程(比如聚宽)是发送买入、卖出信号,比如 时间、买入100股,价格、代码、平安银行,然后在redis本地进行接收,解析,打印并且执行任务(比如QMT、miniQMT进行实盘买入下单)

前一个帖子我们已经知道怎么在windows上搭建redis环境,这个教程我们来学习用python进行发送、接收信号。

目录

一、说明

二、统一消息格式(JSON)

三、sender.py(远端发送)

四、worker.py(本地接收并执行)

五、结语


一、说明

  • sender.py:远端发送买卖信号(入队)

  • worker.py:本地常驻进程,阻塞式取队列、解析、打印并"执行任务"

  • 统一消息格式(JSON)

依赖:
pip install redis

二、统一消息格式(JSON)

复制代码
{
  "type": "BUY",            // BUY 或 SELL
  "symbol": "000001.SZ",    // 证券代码
  "name": "平安银行",        // 可选
  "qty": 100,               // 数量(股/手)
  "price": 12.34,           // 价格,允许 0 表示市价或由执行侧自行决定
  "client_order_id": "...", // 唯一ID(便于去重/追踪)
  "ts": "2025-09-03T17:20:15.123Z"  // ISO时间
}

{

"type": "BUY", // BUY 或 SELL

"symbol": "000001.SZ", // 证券代码

"name": "平安银行", // 可选

"qty": 100, // 数量(股/手)

"price": 12.34, // 价格,允许 0 表示市价或由执行侧自行决定

"client_order_id": "...", // 唯一ID(便于去重/追踪)

"ts": "2025-09-03T17:20:15.123Z" // ISO时间

}

三、sender.py(远端发送)

复制代码
# sender.py
import argparse
import json
import uuid
from datetime import datetime, timezone
import redis
import os

def get_redis():
    r = redis.Redis(
        host=os.getenv("REDIS_HOST", "127.0.0.1"),
        port=int(os.getenv("REDIS_PORT", "6379")),
        password=os.getenv("REDIS_PASSWORD", None),
        db=int(os.getenv("REDIS_DB", "0")),
        decode_responses=True,
        socket_timeout=5
    )
    # 测连通
    r.ping()
    return r

def build_message(side, symbol, qty, price, name=None):
    return {
        "type": side.upper(),             # BUY / SELL
        "symbol": symbol,
        "name": name,
        "qty": int(qty),
        "price": float(price),
        "client_order_id": str(uuid.uuid4()),
        "ts": datetime.now(timezone.utc).isoformat()
    }

def main():
    parser = argparse.ArgumentParser(description="Push trade signal to Redis queue")
    parser.add_argument("--side", choices=["BUY", "SELL"], required=True, help="BUY or SELL")
    parser.add_argument("--symbol", required=True, help="like 000001.SZ")
    parser.add_argument("--qty", type=int, required=True, help="quantity")
    parser.add_argument("--price", type=float, required=True, help="price (0 for market)")
    parser.add_argument("--name", default=None, help="security name, e.g. 平安银行")
    parser.add_argument("--queue", default="trade_queue", help="redis list key")
    args = parser.parse_args()

    r = get_redis()
    msg = build_message(args.side, args.symbol, args.qty, args.price, args.name)
    r.rpush(args.queue, json.dumps(msg, ensure_ascii=False))
    print("Enqueued:", msg)

if __name__ == "__main__":
    main()

使用:

在远程电脑上执行,

环境变量

set REDIS_HOST=你的本地公网IP或内网IP

set REDIS_PASSWORD=123456

然后执行发送代码:【注意,可以等先启动了接收程序再启动发送,这样能看到效果】

python sender.py --side BUY --symbol 000001.SZ --qty 100 --price 12.34 --name 平安银行

注意:macos的话用 export来代替set

四、worker.py(本地接收并执行)

复制代码
# worker.py
import json
import time
import redis
import os
import traceback

QUEUE_KEY = os.getenv("QUEUE_KEY", "trade_queue")
DEAD_KEY  = os.getenv("DEAD_KEY",  "trade_dead")  # 可选死信队列

def get_redis():
    r = redis.Redis(
        host=os.getenv("REDIS_HOST", "127.0.0.1"),
        port=int(os.getenv("REDIS_PORT", "6379")),
        password=os.getenv("REDIS_PASSWORD", None),
        db=int(os.getenv("REDIS_DB", "0")),
        decode_responses=True,
        socket_timeout=10
    )
    r.ping()
    return r

def validate(msg: dict):
    required = ["type", "symbol", "qty", "price", "client_order_id", "ts"]
    for k in required:
        if k not in msg:
            raise ValueError(f"missing field: {k}")
    if msg["type"] not in ("BUY", "SELL"):
        raise ValueError("type must be BUY or SELL")
    if not isinstance(msg["qty"], int) or msg["qty"] <= 0:
        raise ValueError("qty must be positive int")
    # 价格可为0(如表示市价或由执行端决定)
    float(msg["price"])

def execute_trade(msg: dict):
    """
    这里写你的实际执行逻辑(下单、回测接口、模拟撮合、调用券商API等)。
    为了演示,先做个"打印执行"的占位。
    """
    side = msg["type"]
    symbol = msg["symbol"]
    name = msg.get("name") or ""
    qty = msg["qty"]
    price = msg["price"]
    cid = msg["client_order_id"]

    # ===== 在这替换成你的交易执行 =====
    print(f"[EXECUTE] {side} {qty} {symbol} ({name}) @ {price}  CID={cid}")
    # 例如:broker_api.place_order(side=side, symbol=symbol, qty=qty, price=price, tif="GFD")
    # 返回报单号 / 状态,写入日志或回写状态即可。
    # =================================

def main():
    r = get_redis()
    print(f"Worker started. Listening on list: {QUEUE_KEY}")
    while True:
        try:
            # BLPOP: 阻塞等待,timeout=5秒可让我们有机会处理中断/心跳等
            item = r.blpop(QUEUE_KEY, timeout=5)
            if item is None:
                # 队列暂时为空,循环继续
                continue

            _, payload = item
            try:
                msg = json.loads(payload)
            except Exception:
                print("[ERROR] JSON decode failed. Put to dead-letter.")
                r.rpush(DEAD_KEY, payload)
                continue

            try:
                validate(msg)
            except Exception as e:
                print(f"[ERROR] Invalid message: {e}. Put to dead-letter.")
                r.rpush(DEAD_KEY, json.dumps({
                    "error": str(e),
                    "payload": msg
                }, ensure_ascii=False))
                continue

            # 执行任务
            execute_trade(msg)

        except KeyboardInterrupt:
            print("Worker stopping (Ctrl+C).")
            break
        except redis.exceptions.ConnectionError as e:
            print(f"[WARN] Redis connection issue: {e}. Retry in 3s...")
            time.sleep(3)
        except Exception:
            print("[ERROR] Unexpected error:\n", traceback.format_exc())
            # 不中断进程,继续监听
            time.sleep(1)

if __name__ == "__main__":
    main()

在命令行中:

set REDIS_PASSWORD=123456

然后再执行:

python worker.py

结果如图:

说明已经接收到对应信息!成功!

注意:在此之前,要保证redis是启动状态

五、结语

只需要将 execute_trade() 函数改成真实的QMT下单函数,就能够进行实盘交易了。

相关推荐
2601_9548118210 分钟前
AI科学实验室MHS标准解读:AI智能体如何统一控制实验室设备接口
人工智能·python
一位正在转型AI全栈的前端工程师10 分钟前
AI 全栈学习之旅 -Week 9:什么是AI Agent?从Function Calling到LangGraph
前端·python
用户03321266636712 分钟前
使用 Python 为 PowerPoint 设置背景色和背景图【附代码示例】
python
ever_up97328 分钟前
LangChain基础知识概述1
人工智能·python·langchain
深蓝电商API28 分钟前
Redis 在分布式爬虫中的作用
redis·分布式·爬虫
asdzx671 小时前
Python 实现 PDF 文本查找与高亮标注
开发语言·python·pdf
zander2581 小时前
LeetCode 1143. 最长公共子序列
开发语言·python·算法
轩情吖2 小时前
Python基础知识点完整总结
python·字符串·编程语言·函数·列表·元组·字典
编码者卢布2 小时前
【Azure Function】NodeJS Function大批量写入到Redis遇见丢失数据情况的分析
redis·microsoft·azure
青 春 记 忆2 小时前
零基础入门python69:为 FastAPI 项目构建可复现 Docker 镜像
python·fastapi·后端开发