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下单函数,就能够进行实盘交易了。

相关推荐
星川皆无恙20 小时前
基于知识图谱+深度学习的大数据NLP医疗知识问答可视化系统(全网最详细讲解及源码/建议收藏)
大数据·人工智能·python·深度学习·自然语言处理·知识图谱
Tipriest_20 小时前
旋转矩阵,齐次变换矩阵,欧拉角,四元数等相互转换的常用代码C++ Python
c++·python·矩阵
周杰伦_Jay20 小时前
【Go/Python/Java】基础语法+核心特性对比
java·python·golang
小鹿学程序20 小时前
jdk配置完之后java -version还是默认的jdk版本如何更改
java·开发语言·python
Pyeako20 小时前
Python数据可视化--matplotlib库
python·matplotlib·数据可视化·画图·pylab
m0_7048878920 小时前
Day 35
python·深度学习·机器学习
华研前沿标杆游学20 小时前
参观深圳比亚迪总部,探索科技,感受中国“智”造魅力
python
爱打代码的小林21 小时前
python基础(逻辑回归例题)
开发语言·python·逻辑回归
qq_2147826121 小时前
pandas“将”迎来v3.0.0大版本更新!
python·pandas
dagouaofei21 小时前
长文档也能转成PPT:AI自动拆分章节并生成页面
人工智能·python·powerpoint