lhr
2024-06-21 09414b22094c35993f331f25ec104b5f74a6d91f
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
import time
import datetime
import decimal
import logging
import threading
from gm.api import *
 
import basic_methods
 
# 赋值账户ID
account_id = 'aaee2221-839c-11ee-a7cd-00163e022aa6'
# 设置token
set_token("6c1dbe95191fb77cced9d805cb9c853805551ddb")
 
# 为当日新增加持仓代码创建一个初始集合
global_addition_position_symbols = set()
 
#  初始化数据的全局化函数
def init_data():
    logging.info("初始化数据开始")
    global  today_date, Pre_trading_day, Double_Pre_trading_day, Next_trading_day
    # 设置token
    set_token("6c1dbe95191fb77cced9d805cb9c853805551ddb")
    # 今日时间初始化
    now = datetime.datetime.now()  # 获取本机时间
    print(f"本机时间::{now}")
    today_date = now.strftime('%Y-%m-%d')  # 获取今日日期参数
    print(f"今日日期{today_date}")
    Pre_trading_day = get_previous_trading_date(exchange='SHSE', date=today_date)  # 获取前一个交易日
    Double_Pre_trading_day = get_previous_trading_date(exchange='SHSE', date=Pre_trading_day)  # 获取上上一个交易日
    Next_trading_day = get_next_trading_date(exchange='SHSE', date=today_date)  # 获取下一个交易日
    print(f"前一个交易日{Pre_trading_day}")
    print(f"上上一个交易日{Double_Pre_trading_day}")
    print(f"下一个交易日{Next_trading_day}")
 
 
 
 
# 给全局context 赋初始值  下文有用
global_context = None
# 第一步:初始化context函数,数据订阅
def init(context):
    global global_context # 在函数内部的一些初始化函数就把他直接全局化了
    global_context = context
    init_data()
    # print(f"global_context==={global_context.account(account_id = account_id).positions()}")
 
    # 初始化仓位管理,主线逻辑才会运行
    # position_management()
 
    # 初始化get_subscribe_data方法函数,下单买逻辑才会运行中。。。【核心主线程,随时考虑其启动顺序】>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    # threading.Thread(target=lambda: get_subscribe_data(), daemon=True).start()
 
    subscribe(symbols='SZSE.000333', frequency='tick', count=5, unsubscribe_previous=True)
    # time.sleep(5)
    # print(f"test===={test}")
 
    # account_finance = context.account(account_id = 'aaee2221-839c-11ee-a7cd-00163e022aa6').cash
    # print(f"账户对象列表==={account_finance}")
    # print(f"资金初始时间==={account_finance.created_at}")
    # print(f"资金变更时间==={account_finance.updated_at}")
 
    # print(f"总资金==={account_finance.nav}")
    # print(f"可用资金==={account_finance.available}")
    # print(f"持仓占用资金==={account_finance.frozen}")
    # print(f"冻结资金==={account_finance.order_frozen}")
    # print(f"盈亏===={account_finance.pnl}")
    # print(f"持仓浮动盈亏==={account_finance.fpnl}")
    # print(f"持仓市值==={account_finance.market_value}")
    # print(f"资金余额==={account_finance.balance}")
    # print(f"累计出入金额==={account_finance.cum_inout}")
    # print(f"累计交易金额==={account_finance.cum_trade}")
    # print(f"累计盈亏==={account_finance.cum_pnl}")
    # print(f"累计委托==={account_finance.cum_commission}")
    # print(f"最后一笔交易==={account_finance.last_trade}")
    # print(f"最后一笔委托==={account_finance.last_commission}")
    # print(f"最后一笔出入金额==={account_finance.last_inout}")
    # print(f"允许保释??==={account_finance.enable_bail}")
    # print(f"纯浮动盈亏??==={account_finance.fpnl_diluted}")
    # 保持开启 , 为了实现永不完成这堆初始化线程 ,因为一旦完成,整体获取current数据变慢为15S+
    while True:  # 不得擅动!!!
        time.sleep(10)
 
 
 
 
# 获取tick数据
def on_tick(context, tick):
    print(f"tick==={tick}")
    pass
    print(f"tick==={tick}")
    __process(tick)
 
 
# 初始化 subscribe_datas 数据
# subscribe_datas = None
# 获取subscribe_data数据 。
def get_subscribe_data():
    set_token("6c1dbe95191fb77cced9d805cb9c853805551ddb")
    logging.info(f"get_subscribe_data进入")
    while True:
        # logging.info(f"运行中...")
        # print(f"运行中...")
        # 获取当前时间
        # now = time.time()
        try:
            now_start = time.time()
            # print(f"now_start=={now_start}")
            subscribe_datas = subscribe('SHSE.603839,SHSE.6003839,SHSE.600805', frequency='tick', count=1, unsubscribe_previous=False)
            now_end = time.time()
            # print(f"now_end=={now_end}")
            now_start_to_end = now_end - now_start
            for subscribe_data in subscribe_datas:
                # print(f"subscribe_data==={subscribe_data}")
                try:
                    __process(subscribe_data)
                except Exception as e:
                    logging.exception(e)
                    # basic_info = basic_info_symbols_dict.get(subscribe_data['symbol'])
                    print("异常:", subscribe_data)
 
            print(f"now_start_to_end==={round(now_start_to_end, 2)} 秒")
        except Exception as e:
            logging.exception(e)
 
 
def __process(subscribe_data):
    symbol = subscribe_data['symbol']
    print(f"symbol===={symbol}")
 
# 为持仓代码创建一个初始集合
global_position_symbols = set()
 
# 仓位管理策略(核心逻辑流程:先卖后买,止盈止损)
# 如果有持仓,那么就看开盘价是否为涨停价(是则不卖,炸板则卖),开盘价是否为当日涨幅>5%(是则不卖,走跌则卖),否则开盘走跌振幅大于1.5%则卖。
def position_management():
    # 仓位管理及查询函数
    def position_query():
        Account_positions = global_context.account(account_id = account_id).positions()  # 查询当前账户全部持仓
        # print(f"Account_positions==={Account_positions}")
        for d in Account_positions:
            global_position_symbols.add(d['symbol'])
        print(
            f"仓位管理前持仓===============================================================【{global_position_symbols}】")
        print(
            f"仓位管理前持仓数量===============================================================【{len(global_position_symbols)}】")
        for d in Account_positions:
            symbol = d['symbol']
            symbol_code = symbol.split('.')[1]  # 将symbol转为纯数字编号
            available_now = d['available_now']
            # price = d['price']   #当前行情价,,,非最新价,没有实际意义不要用!!!
            vwap = d['vwap']
            volume = d['volume']
            volume_today = d['volume_today']
            volume_yesterday = volume - volume_today
            new_price = current(symbol, fields='price')[0]['price']
            # print(symbol,available_now, price, vwap)
            instruments = get_instruments(symbols=symbol, exchanges=None, sec_types=None, names=None,
                                          fields="symbol,sec_name,pre_close,upper_limit",
                                          df=False)
            if available_now != 0:  # 如果可用资金不等于0  昨日收盘价获取到非0值时(不知名原因导致有些票会获取到0值导致后续公式报错,阻止intraday_growth函数正常运行)
                # print(f"持仓可用股{symbol}")
                history_data = history(symbol=symbol, frequency='1d', start_time=Double_Pre_trading_day,
                                       end_time=Pre_trading_day, fields='open, close, low, high, eob',
                                       adjust=ADJUST_PREV, df=False)
                # print(f"len(history_data)==={len(history_data)}history_data========={history_data} ")
                print(
                    f"【{instruments[0]['sec_name']}】上个交易日 最高{history_data[1]['high']},收盘{history_data[1]['close']}")
                # 获取昨日涨停价 目前函数中的pre_close应该传入前天的收盘价,而非昨天的
                yesterday_limit_up_price = basic_methods.limit_up_price(history_data[0]['close'])
                today_limit_up_price = basic_methods.limit_up_price(history_data[1]['close'])
                # print(f'涨停价算对了吗?{yesterday_top_price}')
                if history_data[0]['close'] == 0:
                    print(f"{symbol}的修改后的history_data的昨日收盘价也为000000000000000000")
                today_growth = basic_methods.intraday_growth(new_price, history_data[1]['close'])
                # 如果持仓股 昨日未涨停 并且 今日最新价不等于今日涨停价 并且 今日涨幅小于3%
                if abs(yesterday_limit_up_price - float(decimal.Decimal(history_data[1]['close']))) < 0.001:
                    print(
                        f"昨日涨停  不卖!【{instruments[0]['sec_name']}】它的今日涨幅为{today_growth}。它的最新价:{new_price},它的昨日收盘价:{history_data[1]['close']},它的昨日涨停价{yesterday_limit_up_price}")
                elif today_limit_up_price == new_price:
                    print(
                        f"今日涨停  不卖!【{instruments[0]['sec_name']}】它的今日涨幅为{today_growth}。它的最新价:{new_price},它的昨日收盘价:{history_data[1]['close']},它的昨日涨停价{yesterday_limit_up_price}")
                elif today_growth > 2:
                    print(
                        f"开盘涨幅大于2%  不卖!【{instruments[0]['sec_name']}】它的今日涨幅为{today_growth}。它的最新价:{new_price},它的昨日收盘价:{history_data[1]['close']},它的昨日涨停价{yesterday_limit_up_price}")
                else:
                    print(f"卖前持仓数量{len(global_position_symbols)}")
                    sell_order(symbol, volume_yesterday, instruments[0]['sec_name'])
                    if history_data[1]['close'] == history_data[1]['high']:
                        print(f"昨日涨停可能判断出错!!!{instruments[0]['sec_name']}")
                    print(
                        f"持仓可用今日开盘涨幅【{instruments[0]['sec_name']}】,它的今日涨幅为{today_growth}。它的最新价:{new_price},它的昨日收盘价:{history_data[1]['close']},它的昨日涨停价{yesterday_limit_up_price},它的前日收盘价:{history_data[0]['close']}")
                # print(f"持仓股 历史数据{history_data}")
                print(f"--------------------------------------------------------------------------------------[分割线]")
            if available_now == 0:  # 如果可用资金等于0,又在持仓中,就是今天新增持仓
                global_addition_position_symbols.add(symbol)
        print(f"今日新增持仓数量==【{len(global_addition_position_symbols)}】")
 
    # 仓位管理时间定时执行函数  (默认设定为9:31)
    def check_time():
        # now = global_context.now  # 获取当前时间
        now = datetime.datetime.now()
        hour = now.hour
        minute = now.minute
        if hour > 9 or (hour == 9 and minute >= 31):
            print(f"开盘时间到了:{now}")
            position_query()
            return False  # 返回False,表示结束循环
        else:
            return True  # 返回True,表示继续循环
 
    # 使用while循环和check_time函数检查时间,并设置固定的时间间隔
    while check_time():
        time.sleep(1)
 
# 下单卖出函数(以手数卖)
def sell_order(symbol, volume_yesterday, sec_name):
    set_account_id('aaee2221-839c-11ee-a7cd-00163e022aa6')
    print(f"命令卖掉【{sec_name}】")
    order_volume(symbol=symbol, volume=volume_yesterday, side=OrderSide_Sell, order_type=OrderType_Market,
                 position_effect=PositionEffect_Close)
    print(f"卖票结果提示:下单成功:【{sec_name}】")
    # 卖票后移除持仓代码集合
    # global_position_symbols.remove(symbol)
    # print(f"卖后持仓数量{len(global_position_symbols)}")
 
 
# 下单买入函数(以价钱买)
def buy_order(current_data,ratio_value):
    now = datetime.datetime.now()
    hour = now.hour
    minute = now.minute
    if hour > 9 or (hour == 9 and minute >= 30):
        set_account_id('aaee2221-839c-11ee-a7cd-00163e022aa6')
        result = order_value(symbol=current_data['symbol'], value=ratio_value, side=OrderSide_Buy, order_type=OrderType_Market,
                    position_effect=PositionEffect_Open)
        print(f"result===={result}")
        print('下单成功', current_data['symbol'])
        # global_position_symbols.add(current_data['symbol'])
        # global_addition_position_symbols.add(current_data['symbol'])
        # print(f"当前持仓数量:::{len(global_position_symbols)}")
        # print(f"今日新增持仓数量:::{len(global_addition_position_symbols)}")
    else:
        print('未到开盘时间不允许下单', current_data['symbol'])
 
 
# 模式选择
if __name__ == '__main__':
    '''
    strategy_id策略ID,由系统生成
    filename文件名,请与本文件名保持一致
    mode实时模式:MODE_LIVE回测模式:MODE_BACKTEST
    token绑定计算机的ID,可在系统设置-密钥管理中生成
    backtest_start_time回测开始时间
    backtest_end_time回测结束时间
    backtest_adjust股票复权方式不复权:ADJUST_NONE前复权:ADJUST_PREV后复权:ADJUST_POST
    backtest_initial_cash回测初始资金
    backtest_commission_ratio回测佣金比例
    backtest_slippage_ratio回测滑点比例
    '''
    run(
        strategy_id='507bb60a-a919-11ee-b6ad-0ae0afd621cd',
        filename='position_management.py',
        mode=MODE_LIVE,  # 实时模式
        # mode=MODE_BACKTEST,    #回测模式
        token='6c1dbe95191fb77cced9d805cb9c853805551ddb',
        backtest_start_time='2024-06-11 09:30:00',
        backtest_end_time='2024-06-11 10:00:00',
        backtest_adjust=ADJUST_PREV,
        backtest_initial_cash=500000,  # 实时模式测试状态下帐户金额由掘金客户端所连接的账户绑定,所以在客户端去充值就可以了(虚拟充值)
        backtest_commission_ratio=0.0001,
        backtest_slippage_ratio=0.0001)