def collect_his_trading(stock_number, stock_name): if stock_number.startswith('6'): req_url = history_trading.format(stock_number+'01') else: req_url = history_trading.format(stock_number+'02') his_html = send_request(req_url) his_soup = BeautifulSoup(his_html, 'lxml') his_table = his_soup.find('table', id='tablefont') if his_table: his_data = his_table.find_all('tr')[1:] for i in his_data: date = datetime.datetime.strptime(i.find('p', class_='date').text, '%Y-%m-%d') today_opening_price = float(i.find_all('td')[1].text.replace(' ', '').strip()) today_highest_price = float(i.find_all('td')[2].text.replace(' ', '').strip()) today_lowest_price = float(i.find_all('td')[3].text.replace(' ', '').strip()) today_closing_price = float(i.find_all('td')[4].text.replace(' ', '').strip()) increase_rate = i.find_all('td')[5].text.replace(' ', '').strip() + '%' increase_amount = float(i.find_all('td')[6].text.replace(' ', '').strip()) turnover_rate = i.find_all('td')[7].text.replace(' ', '').strip() + '%' if float(increase_rate.replace('%', '')) == 0.0 and float(turnover_rate.replace('%', '')) == 0.0: # 去掉停牌期间的行情数据 continue if not check_exists(stock_number, date): sdt = SDT(stock_number=stock_number, stock_name=stock_name, date=date, today_opening_price=today_opening_price, today_highest_price=today_highest_price, today_lowest_price=today_lowest_price, today_closing_price=today_closing_price, increase_rate=increase_rate, increase_amount=increase_amount, turnover_rate=turnover_rate) sdt.save()
def start_quant_analysis(**kwargs): """ :param kwargs:{ qr_date: 运行策略时间 } :return: """ if not kwargs.get('qr_date'): print('no qr_date') return if not kwargs.get('quant_stock'): print('not quant_stock funtion') return if not SDT.objects(date=kwargs['qr_date']) and not kwargs.get('real_time'): print('Not a Trading Date') return try: all_stocks = StockInfo.objects() except Exception as e: logging.error('Error when query StockInfo:' + str(e)) raise e stocks_count = all_stocks.count() skip = 0 quant_res = [] while skip < stocks_count: try: stocks = StockInfo.objects().skip(skip).limit(query_step) except Exception as e: logging.error('Error when query skip %s StockInfo:%s' % (skip, e)) stocks = [] for i in stocks: if i.account_firm and u'瑞华会计师' in i.account_firm: # 过滤瑞华的客户 continue if not kwargs.get('real_time') and\ not SDT.objects(Q(date=kwargs['qr_date']) & Q(stock_number=i.stock_number)): continue qr = '' kwargs['industry_involved'] = i.industry_involved try: qr = kwargs['quant_stock'](i.stock_number, i.stock_name, **kwargs) except Exception as e: logging.error('Error when quant %s ma strategy: %s' % (i.stock_number, e)) if isinstance(qr, QR): quant_res.append(qr) skip += query_step return quant_res
def quant_stock(stock_number, stock_name, **kwargs): real_time = kwargs.get('real_time', False) strategy_direction = 'long' strategy_name = 'break_through_%s_%s_%s' % ( strategy_direction, kwargs['short_ma'], kwargs['long_ma']) sdt = SDT.objects( Q(stock_number=stock_number) & Q(today_closing_price__ne=0.0) & Q(date__lte=kwargs['qr_date'])).order_by( '-date')[:kwargs['long_ma'] + 10] if not sdt: return if float(sdt[0].increase_rate.replace('%', '')) > 9: return if sdt[0].today_closing_price <= sdt[0].today_average_price: return if sdt[0].turnover_amount <= sdt[1].turnover_amount: return if real_time: today_sdt = SDT.objects(date=kwargs['qr_date']) if kwargs['qr_date'] == datetime.date.today() and not today_sdt: today_trading = kwargs.get('today_trading', {}) if not today_trading.get(stock_number): return if float( today_trading.get(stock_number).increase_rate.replace( '%', '')) > 9: return sdt = list(sdt) sdt.insert(0, today_trading.get(stock_number)) trading_data = format_trading_data(sdt) df = calculate_ma(DataFrame(trading_data), short_ma, long_ma) today = df.iloc[-1] yestoday = df.iloc[-2] break_through = 1.8 if yestoday['close_price'] < yestoday['short_ma'] and yestoday['close_price'] < yestoday['long_ma']\ and today['close_price'] > today['short_ma'] and today['close_price'] > today['long_ma']: if today['quantity_relative_ratio'] > break_through or\ today['turnover_amount']/float(yestoday['turnover_amount']) > break_through: qr = QR(stock_number=stock_number, stock_name=stock_name, date=today.name, strategy_direction=strategy_direction, strategy_name=strategy_name, init_price=today['close_price']) if real_time: return qr if not check_duplicate_strategy(qr): qr.save() return qr return ''
def quant_stock(stock_number, stock_name, **kwargs): real_time = kwargs.get('real_time', False) sdt = SDT.objects(Q(stock_number=stock_number) & Q(today_closing_price__ne=0.0) & Q(date__lte=kwargs['qr_date'])).order_by('-date')[:ema_volume] if len(sdt) < ema_volume-50: return if float(sdt[0].increase_rate.replace('%', '')) > 9: return if real_time: today_sdt = SDT.objects(date=kwargs['qr_date']) if kwargs['qr_date'] == datetime.date.today() and not today_sdt: today_trading = kwargs.get('today_trading', {}) if not today_trading.get(stock_number): return sdt = list(sdt) sdt.insert(0, today_trading.get(stock_number)) trading_data = format_trading_data(sdt) df = calculate_macd(DataFrame(trading_data), kwargs['short_ema'], kwargs['long_ema'], kwargs['dif_ema']) df = calculate_ma(df, kwargs['short_ma'], kwargs['long_ma']) today_analysis = df.iloc[-1] yestoday_analysis = df.iloc[-2] if short_ma <= long_ma: strategy_direction = 'long' else: strategy_direction = 'short' strategy_name = 'ma_macd_%s_%s_%s' % (strategy_direction, short_ma, long_ma) if today_analysis['diff_ma'] > 0 > yestoday_analysis['diff_ma']: qr = '' if strategy_direction == 'long': if today_analysis['macd'] > 0 > today_analysis['dif'] and today_analysis['dea'] < 0: qr = QR( stock_number=stock_number, stock_name=stock_name, date=today_analysis.name, strategy_direction=strategy_direction, strategy_name=strategy_name, init_price=today_analysis['close_price'] ) elif strategy_direction == 'short': if today_analysis['macd'] < 0 < today_analysis['dif'] and today_analysis['dea'] > 0: qr = QR( stock_number=stock_number, stock_name=stock_name, date=today_analysis.name, strategy_direction=strategy_direction, strategy_name=strategy_name, init_price=today_analysis['close_price'] ) if isinstance(qr, QR): if real_time: return qr if not check_duplicate_strategy(qr): qr.save() return qr return ''
def collect_datayes_data(date): url = datayes_day_trading.format(date.strftime('%Y%m%d')) datayes_data = send_requests(url) if datayes_data.get('retCode') != 1: return trading_data = datayes_data.get('data', []) for i in trading_data: is_open = i['isOpen'] if is_open != 1: continue stock_number = i['ticker'] stock_name = i['secShortName'] yesterday_closed_price = i['actPreClosePrice'] today_opening_price = i['openPrice'] today_closing_price = i['closePrice'] today_highest_price = i['highestPrice'] today_lowest_price = i['lowestPrice'] turnover_amount = int(i['turnoverValue'] / 10000) turnover_volume = int(i['turnoverVol'] / 100) increase_amount = i['closePrice'] - i['actPreClosePrice'] increase_rate = str( round(increase_amount / i['actPreClosePrice'], 4) * 100) + '%' turnover_rate = str(i['turnoverRate'] * 100) + '%' total_stock = int(i['marketValue'] / i['closePrice']) circulation_stock = int(i['negMarketValue'] / i['closePrice']) date = datetime.datetime.strptime(i['tradeDate'], '%Y-%m-%d') sdt = SDT(stock_number=stock_number, stock_name=stock_name, yesterday_closed_price=yesterday_closed_price, today_opening_price=today_opening_price, today_closing_price=today_closing_price, today_highest_price=today_highest_price, today_lowest_price=today_lowest_price, turnover_amount=turnover_amount, turnover_volume=turnover_volume, increase_amount=increase_amount, increase_rate=increase_rate, turnover_rate=turnover_rate, total_stock=total_stock, circulation_stock=circulation_stock, date=date) try: if not check_duplicate(sdt): sdt.save() except Exception, e: logging.error('Error when query or saving %s data:%s' % (sdt.stock_number, e))
def quant_stock(stock_number, stock_name, **kwargs): short_ma = kwargs['short_ma'] long_ma = kwargs['long_ma'] qr_date = kwargs['qr_date'] real_time = kwargs.get('real_time', False) if short_ma <= long_ma: strategy_direction = 'long' quant_count = long_ma + 5 else: strategy_direction = 'short' quant_count = short_ma + 5 strategy_name = 'ma_%s_%s_%s' % (strategy_direction, short_ma, long_ma) sdt = SDT.objects( Q(stock_number=stock_number) & Q(today_closing_price__ne=0.0) & Q(date__lte=qr_date)).order_by('-date')[:quant_count] if len(sdt) < quant_count: # trading data not enough return if float(sdt[0].increase_rate.replace('%', '')) > 9: return if real_time: today_sdt = SDT.objects(date=kwargs['qr_date']) if kwargs['qr_date'] == datetime.date.today() and not today_sdt: today_trading = kwargs.get('today_trading', {}) if not today_trading.get(stock_number): return sdt = list(sdt) sdt.insert(0, today_trading.get(stock_number)) trading_data = format_trading_data(sdt) if not trading_data: return df = calculate_ma(DataFrame(trading_data), short_ma, long_ma) today_ma = df.iloc[-1] yestoday_ma = df.iloc[-2] if today_ma['diff_ma'] > 0 > yestoday_ma['diff_ma']: qr = QR(stock_number=stock_number, stock_name=stock_name, date=today_ma.name, strategy_direction=strategy_direction, strategy_name=strategy_name, init_price=today_ma['close_price']) if real_time: return qr if not check_duplicate_strategy(qr): qr.save() return qr return ''
def fetch_stock_price(stock_number, date): sdt = SDT.objects(Q(stock_number=stock_number) & Q(date=date)) if sdt: return sdt.first() else: return 0
def quant_stock(stock_number, short_ma_num, long_ma_num, qr_date): sdt = SDT.objects( Q(stock_number=stock_number) & Q(today_closing_price__ne=0.0) & Q(date__lte=qr_date)).order_by('-date') if not sdt: # return if not trading data return if len(sdt[:short_ma_num]) < short_ma_num or len( sdt[:long_ma_num]) < long_ma_num: # trading data not enough return if short_ma_num <= long_ma_num: strategy_direction = 'long' else: strategy_direction = 'short' strategy_name = 'ma_%s_%s_%s' % (strategy_direction, short_ma_num, long_ma_num) short_ma_list = calculate_ma_list(sdt[:short_ma_num + 5], short_ma_num, 2, qr_date) long_ma_list = calculate_ma_list(sdt[:long_ma_num + 5], long_ma_num, 2, qr_date) ma_difference = calculate_ma_difference(short_ma_list, long_ma_list) if ma_difference[0] > 0 > ma_difference[1]: """ 当短期均线向上穿过长期均线的时候 """ save_quant_result(sdt[0], strategy_name, strategy_direction)
def quant_stock(stock_number, stock_name, **kwargs): qr_date = kwargs['qr_date'] week_long = kwargs.get('week_long', False) if not pre_sdt_check(stock_number, **kwargs): return strategy_name = 'goup_staying' if week_long: strategy_name = 'weeklong_' + strategy_name sdt = SDT.objects( Q(stock_number=stock_number) & Q(today_closing_price__ne=0.0) & Q(date__lte=qr_date)).order_by('-date')[:quant_count] if len(sdt) < quant_count: return if float(sdt[0].increase_rate.replace('%', '').strip()) > goup_stay: qr = QR(stock_number=stock_number, stock_name=stock_name, date=qr_date, strategy_direction='long', strategy_name=strategy_name, init_price=sdt[0].today_closing_price, industry_involved=kwargs.get('industry_involved'), increase_rate=float(sdt[0].increase_rate.replace('%', '').strip())) if not check_duplicate_strategy(qr): qr.save() return qr
def start_quant_analysis(**kwargs): if not SDT.objects(date=kwargs['date']): print 'Not a Trading Day' return stock_count = StockInfo.objects().count() skip = 0 while skip < stock_count: try: stocks = StockInfo.objects().skip(skip).limit(step) except Exception, e: logging.error('Error when query StockInfo:' + str(e)) stocks = [] for s in stocks: if s.account_firm and u'瑞华会计师' in s.account_firm: # 过滤瑞华的客户 continue try: quant_stock(s.stock_number, s.stock_name, **kwargs) except Exception, e: logging.error('Error when macd quant %s:%s' % (s.stock_number, e))
def strategy_statistics(strategy_name): all_qr = QR.objects(strategy_name=strategy_name) if not all_qr: print "Wrong Strategy Name!" return trading_date = SDT.objects(stock_number__startswith="300").distinct("date") trading_date.sort() bt_result = {} for d in trading_date: bt_result[str(d.date())] = back_test_success(strategy_name, d) frame = DataFrame(bt_result) pd.set_option("display.width", 200) pd.set_option("display.max_rows", 400) print frame.reindex( [ "count", "one_back_test", "one_yield_expectation", "three_back_test", "three_yield_expectation", "five_back_test", "five_yield_expectation", ] ).T pd.set_option("display.width", None) pd.set_option("display.max_rows", None)
def quant_stock(stock_number, short_ma_num, long_ma_num, qr_date): if short_ma_num <= long_ma_num: strategy_direction = 'long' quant_count = long_ma_num + 5 else: strategy_direction = 'short' quant_count = short_ma_num + 5 strategy_name = 'ma_%s_%s_%s' % (strategy_direction, short_ma_num, long_ma_num) sdt = SDT.objects(Q(stock_number=stock_number) & Q(today_closing_price__ne=0.0) & Q(date__lte=qr_date)).order_by('-date')[:quant_count] if len(sdt) < quant_count: # trading data not enough return trading_data = format_trading_data(sdt, qr_date) if not trading_data: return df = DataFrame(trading_data).set_index(['date']) df['short_ma'] = df['price'].rolling(window=short_ma_num, center=False).mean() df['long_ma'] = df['price'].rolling(window=long_ma_num, center=False).mean() df['diff'] = df['short_ma'] - df['long_ma'] today_ma = df.iloc[-1] yestoday_ma = df.iloc[-2] if today_ma['diff'] > 0 > yestoday_ma['diff']: qr = QR( stock_number=stock_number, stock_name=today_ma['stock_name'], date=today_ma.name, strategy_direction=strategy_direction, strategy_name=strategy_name, init_price=today_ma['price'] ) if not check_duplicate(qr): qr.save()
def test_by_day(qr, day): if isinstance(qr, QR): sdt = SDT.objects(Q(stock_number=qr.stock_number) & Q(date__gt=qr.date)).order_by('date') if sdt.count() >= day: back_test_sdt = sdt[day-1] if back_test_sdt.today_closing_price == 0.0: # 去掉停牌的情况 return qr[test_pattern[day]['price']] = back_test_sdt.today_closing_price price_spread = back_test_sdt.today_closing_price - qr.init_price if qr.strategy_direction == 'long': if price_spread >= 0: qr[test_pattern[day]['test']] = True else: qr[test_pattern[day]['test']] = False elif qr.strategy_direction == 'short': if price_spread > 0: qr[test_pattern[day]['test']] = False else: qr[test_pattern[day]['test']] = True qr.save()
def quant_stock(stock_number, short_ma_num, long_ma_num, qr_date, half_year=False): sdt = SDT.objects(Q(stock_number=stock_number) & Q(today_closing_price__ne=0.0) & Q(date__lte=qr_date)).order_by('-date') trading_data = list(sdt) if len(trading_data) < long_ma_num + 5 or len(trading_data) < short_ma_num + 5: """ 如果交易数据不够,跳过 """ return if half_year and sdt.count() >= 120: today_price = sdt[0].today_closing_price avg_price = sdt.limit(120).average('today_closing_price') if today_price < avg_price: return if short_ma_num <= long_ma_num: strategy_direction = 'long' else: strategy_direction = 'short' if half_year: strategy_name = 'ma_halfyear_%s_%s_%s' % (strategy_direction, short_ma_num, long_ma_num) else: strategy_name = 'ma_%s_%s_%s' % (strategy_direction, short_ma_num, long_ma_num) short_ma_list = calculate_ma_list(trading_data, short_ma_num, 2) long_ma_list = calculate_ma_list(trading_data, long_ma_num, 2) ma_difference = calculate_ma_difference(short_ma_list, long_ma_list) if ma_difference[0] > 0 > ma_difference[1]: """ 当短期均线向上穿过长期均线的时候 """ save_quant_result(trading_data[0], strategy_name, strategy_direction)
def check_duplicate(sdt): if isinstance(sdt, SDT): cursor = SDT.objects(Q(stock_number=sdt.stock_number) & Q(date=sdt.date)) if cursor: return True else: return False
def pre_sdt_check(stock_number, **kwargs): """ 依据量价进行预先筛选 :param stock_number: :param qr_date: :return: """ qr_date = kwargs.get('qr_date') rate_value = 0 cursor = SDT.objects(Q(stock_number=stock_number) & Q(today_closing_price__ne=0.0) & Q(date__lte=qr_date))\ .order_by('-date') if not cursor: return False min_total_value = 3000000000 stock_info = StockInfo.objects(stock_number=stock_number) if stock_info and stock_info[ 0].total_value and stock_info[0].total_value < min_total_value: return False max_trade_amount = 5000 avg_trade_amount = 3000 amount_avg_num = 5 amount_sdt = cursor[:amount_avg_num] if cal_turnover_ma(cursor, amount_avg_num) >= avg_trade_amount or\ max([i.turnover_amount for i in amount_sdt]) >= max_trade_amount: rate_value += 1 if rate_value: return True else: return False
def quant_stock(stock_number, stock_name, **kwargs): if not pre_sdt_check(stock_number, **kwargs): return real_time = kwargs.get('real_time', False) sdt = SDT.objects(Q(stock_number=stock_number) & Q(today_closing_price__ne=0.0) & Q(date__lte=kwargs['qr_date'])).order_by('-date')[:ema_volume] if float(sdt[0].increase_rate.replace('%', '')) > 9: return '' if real_time: sdt = setup_realtime_sdt(stock_number, sdt, kwargs) if not sdt: return trading_data = format_trading_data(sdt) df = calculate_macd(DataFrame(trading_data), kwargs['short_ema'], kwargs['long_ema'], kwargs['dif_ema']) today = df.iloc[-1] yestoday = df.iloc[-2] strategy_direction = 'long' if yestoday['dif'] < 0 < today['dif']: strategy_name = 'dif_day_%s_%s_%s_%s' % (strategy_direction, kwargs['short_ema'], kwargs['long_ema'], kwargs['dif_ema']) increase_rate = round((today['close_price'] - yestoday['close_price']) / yestoday['close_price'], 4) * 100 qr = QR( stock_number=stock_number, stock_name=stock_name, date=today.name, strategy_direction=strategy_direction, strategy_name=strategy_name, init_price=today['close_price'], industry_involved=kwargs.get('industry_involved'), increase_rate=increase_rate ) if real_time and strategy_direction == 'long': return qr if not real_time and not check_duplicate_strategy(qr): qr.save() return qr return ''
def quant_stock(stock_number, **kwargs): sdt_li = SDT.objects(Q(stock_number=stock_number) & Q(today_closing_price__ne=0.0) & Q(date__lte=kwargs['date'])).order_by('date') stock_name = sdt_li[0].stock_name trading_data = [] for s in sdt_li: trading_data.append({'date': s.date, 'price': s.today_closing_price, 'total_stock': s.total_stock}) # trading_data = restore_right(trading_data) df = DataFrame(trading_data).set_index(['date']) df['short_ema'] = df['price'].ewm(span=kwargs['short_ema']).mean() df['long_ema'] = df['price'].ewm(span=kwargs['long_ema']).mean() df['dif'] = df['short_ema'] - df['long_ema'] df['dea'] = df['dif'].ewm(span=kwargs['dif_ema']).mean() df['macd'] = df['dif'] - df['dea'] today_macd = df.iloc[-1] yestoday_macd = df.iloc[-2] if today_macd['dif'] < 0 and today_macd['dea'] < 0 < today_macd['macd'] and yestoday_macd['macd'] < 0: strategy_direction = 'long' strategy_name = 'macd_long_%s_%s_%s' % (kwargs['short_ema'], kwargs['long_ema'], kwargs['dif_ema']) qr = QR( stock_number=stock_number, stock_name=stock_name, date=today_macd.name, strategy_direction=strategy_direction, strategy_name=strategy_name, init_price=today_macd['price'] ) if not check_duplicate(qr): qr.save()
def check_duplicate(sdt): """ 检查某一天的交易数据是否与之前一天完全相同,如果完全相同,则不会保存这些交易数据 为了规避一些法定假日不交易的情况,还有股票停牌的时候,停牌中的数据是不记录的 """ if isinstance(sdt, SDT): trading_date = SDT.objects(stock_number=sdt.stock_number).order_by("-date") if trading_date: latest_sdt = trading_date[0] check_item = [ "yesterday_closed_price", "today_opening_price", "today_closing_price", "today_highest_price", "today_lowest_price", "turnover_amount", "turnover_volume", "increase_amount", "increase_rate", "today_average_price", "quantity_relative_ratio", "turnover_rate", ] for i in check_item: if sdt[i] != latest_sdt[i]: return False logging.warning("%s trading data is same with latest STD, this data will not be saved." % sdt.stock_number) return True else: return False
def collect_his_trading(stock_number, stock_name): if stock_number.startswith('6'): req_url = history_trading.format(stock_number+'01') else: req_url = history_trading.format(stock_number+'02') his_html = send_request(req_url) his_soup = BeautifulSoup(his_html, 'lxml') his_table = his_soup.find('table', id='tablefont') if his_table: his_data = his_table.find_all('tr')[1:] for i in his_data: date = datetime.datetime.strptime(i.find('p', class_='date').text.strip(), '%Y-%m-%d') try: today_opening_price = float(i.find_all('td')[1].text.replace(' ', '').strip()) today_highest_price = float(i.find_all('td')[2].text.replace(' ', '').strip()) today_lowest_price = float(i.find_all('td')[3].text.replace(' ', '').strip()) today_closing_price = float(i.find_all('td')[4].text.replace(' ', '').strip()) increase_rate = i.find_all('td')[5].text.replace(' ', '').strip() + '%' increase_amount = float(i.find_all('td')[6].text.replace(' ', '').strip()) turnover_rate = i.find_all('td')[7].text.replace(' ', '').strip() + '%' total_stock = int(i.find_all('td')[10].text.replace(' ', '').replace(',', '').strip()) circulation_stock = int(i.find_all('td')[12].text.replace(' ', '').replace(',', '').strip()) except Exception, e: if '--' not in str(e): logging.error('Collect %s %s trading data failed:%s' % (stock_number, str(date), e)) continue if float(increase_rate.replace('%', '')) == 0.0 and float(turnover_rate.replace('%', '')) == 0.0: # 去掉停牌期间的行情数据 continue if check_exists(stock_number, date): sdt = SDT.objects(Q(stock_number=stock_number) & Q(date=date)).next() if not sdt.total_stock or not sdt.circulation_stock: sdt.total_stock = total_stock sdt.circulation_stock = circulation_stock sdt.save() else: # 添加股本相关数据 sdt = SDT(stock_number=stock_number, stock_name=stock_name, date=date, today_opening_price=today_opening_price, today_highest_price=today_highest_price, today_lowest_price=today_lowest_price, today_closing_price=today_closing_price, increase_rate=increase_rate, increase_amount=increase_amount, turnover_rate=turnover_rate, total_stock=total_stock, circulation_stock=circulation_stock) sdt.save()
def is_new_stock(stock_number, end_date): sdt = SDT.objects( Q(stock_number=stock_number) & Q(date__lt=end_date - datetime.timedelta(days=new_stock_period))) if sdt.count() < new_stock_period: return True else: return False
def collect_his_trading(stock_number, stock_name): if stock_number.startswith("6"): req_url = history_trading.format(stock_number + "01") else: req_url = history_trading.format(stock_number + "02") his_html = send_request(req_url) his_soup = BeautifulSoup(his_html, "lxml") his_table = his_soup.find("table", id="tablefont") if his_table: his_data = his_table.find_all("tr")[1:] for i in his_data: date = datetime.datetime.strptime(i.find("p", class_="date").text, "%Y-%m-%d") try: today_opening_price = float(i.find_all("td")[1].text.replace(" ", "").strip()) today_highest_price = float(i.find_all("td")[2].text.replace(" ", "").strip()) today_lowest_price = float(i.find_all("td")[3].text.replace(" ", "").strip()) today_closing_price = float(i.find_all("td")[4].text.replace(" ", "").strip()) increase_rate = i.find_all("td")[5].text.replace(" ", "").strip() + "%" increase_amount = float(i.find_all("td")[6].text.replace(" ", "").strip()) turnover_rate = i.find_all("td")[7].text.replace(" ", "").strip() + "%" except Exception, e: if "--" not in str(e): logging.error("Collect %s %s trading data failed:%s" % (stock_number, str(date), e)) continue if float(increase_rate.replace("%", "")) == 0.0 and float(turnover_rate.replace("%", "")) == 0.0: # 去掉停牌期间的行情数据 continue if not check_exists(stock_number, date): sdt = SDT( stock_number=stock_number, stock_name=stock_name, date=date, today_opening_price=today_opening_price, today_highest_price=today_highest_price, today_lowest_price=today_lowest_price, today_closing_price=today_closing_price, increase_rate=increase_rate, increase_amount=increase_amount, turnover_rate=turnover_rate, ) sdt.save()
def start_mining_notice(): try: all_stocks = StockInfo.objects() except Exception as e: logging.error('Error when query StockInfo:' + str(e)) raise e stocks_count = len(all_stocks) skip = 0 notice_data = [] while skip < stocks_count: try: stocks = StockInfo.objects().skip(skip).limit(query_step) except Exception as e: logging.error('Error when query skip %s StockInfo:%s' % (skip, e)) stocks = [] for i in stocks: if i.account_firm and u'瑞华会计师' in i.account_firm: # 过滤瑞华的客户 continue sdt = SDT.objects( Q(stock_number=i.stock_number) & Q(date=datetime.date.today())) if not sdt: # 过滤仍在停牌的票 continue try: notice = collect_event_notice(i.stock_number) except Exception as e: logging.error('Error when collect %s notice: %s' % (i.stock_number, e)) if notice: notice_data += notice skip += query_step if not notice_data: return df = DataFrame(notice_data).sort_values(by=['stock_number', 'date'], ascending=[True, True])\ .set_index(['stock_number', 'date']) pd.set_option('display.width', 400) pd.set_option('display.max_colwidth', 150) pd.set_option('display.max_rows', 800) notice_path = '/root/healing-ward/notice_mining/%s.txt' % datetime.date.today( ) notice_data = df.to_string() if exists(notice_path): print(notice_data) else: with codecs.open(notice_path, 'w+', 'utf-8') as fd: fd.write(notice_data) pd.set_option('display.width', None) pd.set_option('display.max_rows', None)
def quant_stock(stock_number, stock_name, **kwargs): short_ma = kwargs['short_ma'] long_ma = kwargs['long_ma'] qr_date = kwargs['qr_date'] week_long = kwargs.get('week_long', False) if not pre_sdt_check(stock_number, **kwargs): return real_time = kwargs.get('real_time', False) if short_ma <= long_ma: strategy_direction = 'long' quant_count = long_ma + 5 else: strategy_direction = 'short' quant_count = short_ma + 5 strategy_name = 'ma_%s_%s_%s' % (strategy_direction, short_ma, long_ma) if week_long: strategy_name = 'weeklong_' + strategy_name sdt = SDT.objects( Q(stock_number=stock_number) & Q(today_closing_price__ne=0.0) & Q(date__lte=qr_date)).order_by('-date')[:quant_count] if len(sdt) < quant_count: # trading data not enough return if real_time: sdt = setup_realtime_sdt(stock_number, sdt, kwargs) if not sdt: return trading_data = format_trading_data(sdt) if not trading_data: return df = calculate_ma(DataFrame(trading_data), short_ma, long_ma) today = df.iloc[-1] yestoday = df.iloc[-2] if today['diff_ma'] > 0 > yestoday['diff_ma']: increase_rate = round( (today['close_price'] - yestoday['close_price']) / yestoday['close_price'], 4) * 100 qr = QR(stock_number=stock_number, stock_name=stock_name, date=today.name, strategy_direction=strategy_direction, strategy_name=strategy_name, init_price=today['close_price'], industry_involved=kwargs.get('industry_involved'), increase_rate=increase_rate) if real_time: return qr if not check_duplicate_strategy(qr): qr.save() return qr return ''
def quant_stock(stock_number, stock_name, **kwargs): week_long = kwargs.get('week_long', False) if not pre_sdt_check(stock_number, **kwargs): return real_time = kwargs.get('real_time', False) sdt = SDT.objects(Q(stock_number=stock_number) & Q(today_closing_price__ne=0.0) & Q(date__lte=kwargs['qr_date'])).order_by('-date')[:ema_volume] if float(sdt[0].increase_rate.replace('%', '')) > 9: return if real_time: sdt = setup_realtime_sdt(stock_number, sdt, kwargs) if not sdt: return trading_data = format_trading_data(sdt) df = calculate_macd(DataFrame(trading_data), kwargs['short_ema'], kwargs['long_ema'], kwargs['dif_ema']) df = calculate_ma(df, kwargs['short_ma'], kwargs['long_ma']) today = df.iloc[-1] yestoday = df.iloc[-2] if short_ma <= long_ma: strategy_direction = 'long' else: strategy_direction = 'short' strategy_name = 'ma_macd_%s_%s_%s' % (strategy_direction, short_ma, long_ma) if week_long: strategy_name = 'weeklong_' + strategy_name if today['diff_ma'] > 0 > yestoday['diff_ma']: increase_rate = round((today['close_price'] - yestoday['close_price']) / yestoday['close_price'], 4) * 100 qr = '' if strategy_direction == 'long': if today['macd'] > 0 > today['dif'] and today['dea'] < 0: qr = QR( stock_number=stock_number, stock_name=stock_name, date=today.name, strategy_direction=strategy_direction, strategy_name=strategy_name, init_price=today['close_price'], industry_involved=kwargs.get('industry_involved'), increase_rate=increase_rate ) elif strategy_direction == 'short': if today['macd'] < 0 < today['dif'] and today['dea'] > 0: qr = QR( stock_number=stock_number, stock_name=stock_name, date=today.name, strategy_direction=strategy_direction, strategy_name=strategy_name, init_price=today['close_price'], industry_involved=kwargs.get('industry_involved'), increase_rate=increase_rate ) if isinstance(qr, QR): if real_time: return qr if not check_duplicate_strategy(qr): qr.save() return qr return ''
def setup_realtime_sdt(stock_number, sdt, kwargs): today_sdt = SDT.objects(date=kwargs['qr_date']) if kwargs['qr_date'] == datetime.date.today() and not today_sdt: today_trading = kwargs.get('today_trading', {}) if not today_trading.get(stock_number): return list() sdt = list(sdt) sdt.insert(0, today_trading.get(stock_number)) return sdt
def quant_stock(): today = datetime.date.today() increase_rate = '5%' quantity_relative_ratio = 2.5 try: sdt = SDT.objects(Q(date=today) & Q(increase_rate__gte=increase_rate) & Q(quantity_relative_ratio__gte=quantity_relative_ratio)) except Exception, e: logging.error('Query DB failed:%s' % e) raise e
def start_quant_analysis(short_ma_num, long_ma_num, qr_date): if not SDT.objects(date=qr_date): print 'Not a Trading Date' return try: all_stocks = StockInfo.objects() except Exception, e: logging.error('Error when query StockInfo:' + str(e)) raise e
def start_quant_analysis(short_ma_num, long_ma_num, qr_date, half_year=False): if not SDT.objects(date=qr_date).count(): print 'Not a Trading Date' return try: all_stocks = StockInfo.objects() except Exception, e: logging.error('Error when query StockInfo:' + str(e)) raise e
def quant_stock(stock_number, stock_name, **kwargs): sdt_li = SDT.objects( Q(stock_number=stock_number) & Q(today_closing_price__ne=0.0) & Q(date__lte=kwargs['date'])).order_by('-date')[:ema_volume] if len(sdt_li) < 20: return trading_data = [] qr_date = kwargs['date'] standard_total_stock = sdt_li[0].total_stock if not standard_total_stock: standard_total_stock = sdt_li[1].total_stock if not standard_total_stock: standard_total_stock = sdt_li[2].total_stock if not standard_total_stock: return for s in sdt_li: total_stock = s.total_stock if total_stock and total_stock != standard_total_stock: today_closing_price = s.today_closing_price * float( total_stock) / float(standard_total_stock) else: today_closing_price = s.today_closing_price trading_data.append({ 'date': s.date, 'price': today_closing_price, 'total_stock': s.total_stock }) trading_data.reverse() df = DataFrame(trading_data).set_index(['date']) df['short_ema'] = df['price'].ewm(span=kwargs['short_ema']).mean() df['long_ema'] = df['price'].ewm(span=kwargs['long_ema']).mean() df['dif'] = df['short_ema'] - df['long_ema'] df['dea'] = df['dif'].ewm(span=kwargs['dif_ema']).mean() df['macd'] = df['dif'] - df['dea'] today_macd = df.iloc[-1] yestoday_macd = df.iloc[-2] if yestoday_macd['macd'] < 0 < today_macd['macd']: strategy_direction = 'long' strategy_name = 'macd_long_%s_%s_%s' % ( kwargs['short_ema'], kwargs['long_ema'], kwargs['dif_ema']) qr = QR(stock_number=stock_number, stock_name=stock_name, date=today_macd.name, strategy_direction=strategy_direction, strategy_name=strategy_name, init_price=today_macd['price']) if not check_duplicate(qr): qr.save()
def cal_buffett_index(): today = datetime.date.today() sdt = SDT.objects(date=today) if not sdt: return bi = BuffettIndex.objects(date=today) if bi: return save_data()
def quant_stock(): today = datetime.date.today() increase_rate = '5%' quantity_relative_ratio = 2.5 try: sdt = SDT.objects( Q(date=today) & Q(increase_rate__gte=increase_rate) & Q(quantity_relative_ratio__gte=quantity_relative_ratio)) except Exception, e: logging.error('Query DB failed:%s' % e) raise e
def quant_stock(stock_number, stock_name, **kwargs): sdt = SDT.objects(Q(stock_number=stock_number) & Q(today_closing_price__ne=0.0) & Q(date__lte=kwargs['qr_date'])).order_by('-date')[:ema_volume] if float(sdt[0].increase_rate.replace('%', '')) > 9: return trading_data = format_trading_data(sdt) df = calculate_ma(DataFrame(trading_data), kwargs['short_ma'], kwargs['long_ma']) df = calculate_macd(df, kwargs['short_ema'], kwargs['long_ema'], kwargs['dif_ema']) today = df.iloc[-1] yestoday = df.iloc[-2]
def setup_realtime_swt(swt, stock_number, qr_date): # 当没有当周数据时,用日线数据补 sdt = SDT.objects(Q(stock_number=stock_number) & Q(date=qr_date)) if not sdt: return list() qr_date_trading = sdt[0] extra_swt = SWT() extra_swt.weekly_close_price = qr_date_trading.today_closing_price extra_swt.last_trade_date = qr_date_trading.date swt = list(swt) swt.insert(0, extra_swt) return swt
def pre_sdt_check(stock_number, **kwargs): """ 依据量价进行预先筛选 :param stock_number: :param qr_date: :return: """ qr_date = kwargs.get('qr_date') if kwargs.get('week_long', False): short_ma = 5 long_ma = 10 if not is_week_long(stock_number, qr_date, short_ma, long_ma): return False rate_value = 0 cursor = SDT.objects(Q(stock_number=stock_number) & Q(today_closing_price__ne=0.0) & Q(date__lte=qr_date))\ .order_by('-date') if not cursor: return False today_sdt = cursor[0] today_closing_price = today_sdt.today_closing_price if today_sdt.year_ma: year_ma = today_sdt.year_ma else: year_ma = cal_year_ma(cursor) try: today_sdt.year_ma = year_ma today_sdt.save() except Exception: pass if today_closing_price >= year_ma: rate_value += 1 max_trade_amount = 2000 avg_trade_amount = 1000 amount_avg_num = 5 amount_sdt = cursor[:amount_avg_num] if cal_turnover_ma(cursor, amount_avg_num) >= avg_trade_amount or\ max([i.turnover_amount for i in amount_sdt]) >= max_trade_amount: rate_value += 1 if rate_value: return True else: return False
def save_index_data(idt): if isinstance(idt, IDT): today = datetime.date.today() sdt = SDT.objects(date=today) if not sdt: return exists_data = IDT.objects(Q(date=today) & Q(index_number=idt.index_number)) if exists_data: return try: idt.save() except Exception, e: logging.error('Error when save market index data:' + str(e))
def quant_stock(stock_number, stock_name, **kwargs): if not pre_sdt_check(stock_number, **kwargs): return real_time = kwargs.get('real_time', False) week_long = kwargs.get('week_long', False) strategy_direction = 'long' strategy_name = 'break_through_%s_%s_%s' % (strategy_direction, kwargs['short_ma'], kwargs['long_ma']) if week_long: strategy_name = 'weeklong_' + strategy_name sdt = SDT.objects(Q(stock_number=stock_number) & Q(today_closing_price__ne=0.0) & Q(date__lte=kwargs['qr_date'])).order_by('-date')[:kwargs['long_ma']+10] if not sdt: return if not real_time: if sdt[0].today_closing_price <= sdt[0].today_average_price: return if real_time: sdt = setup_realtime_sdt(stock_number, sdt, kwargs) if not sdt: return if sdt[0].today_closing_price < sdt[0].today_opening_price: return trading_data = format_trading_data(sdt) df = calculate_ma(DataFrame(trading_data), short_ma, long_ma) today = df.iloc[-1] yestoday = df.iloc[-2] if yestoday['close_price'] < yestoday['long_ma'] and today['close_price'] > today['short_ma']\ and today['close_price'] > today['long_ma']: increase_rate = round((today['close_price'] - yestoday['close_price']) / yestoday['close_price'], 4) * 100 qr = QR( stock_number=stock_number, stock_name=stock_name, date=today.name, strategy_direction=strategy_direction, strategy_name=strategy_name, init_price=today['close_price'], industry_involved=kwargs.get('industry_involved'), increase_rate=increase_rate ) if real_time: return qr if not check_duplicate_strategy(qr): qr.save() return qr return ''
def save_index_data(idt): if isinstance(idt, IDT): today = datetime.date.today() sdt = SDT.objects(date=today) if not sdt: return exists_data = IDT.objects( Q(date=today) & Q(index_number=idt.index_number)) if exists_data: return try: idt.save() except Exception as e: logging.error('Error when save market index data:' + str(e))
def quant_stock(stock_number, short_ma_num=1, long_ma_num=30): strategy_name = 'ma_long_%s_%s' % (short_ma_num, long_ma_num) sdt = SDT.objects( stock_number=stock_number).order_by('-date')[:long_ma_num + 10] if float(sdt[0].increase_rate.replace('%', '')) == 0.0 and float( sdt[0].turnover_rate.replace('%', '')) == 0.0: """ 如果最新一天股票的状态是停牌,跳过 """ return trading_data = [] for i in sdt: """ 去除交易数据里的停牌数据 """ if float(i.increase_rate.replace('%', '')) == 0.0 and float( i.turnover_rate.replace('%', '')) == 0.0: continue else: trading_data.append(i) if len(trading_data) < long_ma_num + 5 or len( trading_data) < short_ma_num + 5: """ 如果交易数据不够,跳过 """ return if short_ma_num <= long_ma_num: strategy_direction = 'long' if float(sdt[0].increase_rate.replace('%', '')) < 0.0: return else: strategy_direction = 'short' if float(sdt[0].increase_rate.replace('%', '')) > 0.0: return short_ma_list = calculate_ma_list(trading_data, short_ma_num, 2) long_ma_list = calculate_ma_list(trading_data, long_ma_num, 2) ma_difference = calculate_ma_difference(short_ma_list, long_ma_list) if ma_difference[0] > 0 > ma_difference[1]: """ 当短期均线向上穿过长期均线的时候 """ save_quant_result(trading_data[0], strategy_name, strategy_direction)
def check_duplicate(trading_data): if isinstance(trading_data, SDT): cursor = SDT.objects( Q(stock_number=trading_data.stock_number) & Q(date=trading_data.date)) if cursor: return True else: return False elif isinstance(trading_data, SWT): cursor = SWT.objects( Q(stock_number=trading_data.stock_number) & Q(first_trade_date=trading_data.first_trade_date)) if cursor: return True else: return False
def quant_stock(stock_number, stock_name, **kwargs): sdt_li = SDT.objects(Q(stock_number=stock_number) & Q(today_closing_price__ne=0.0) & Q(date__lte=kwargs['date'])).order_by('-date')[:ema_volume] if len(sdt_li) < 20: return trading_data = [] qr_date = kwargs['date'] standard_total_stock = sdt_li[0].total_stock if not standard_total_stock: standard_total_stock = sdt_li[1].total_stock if not standard_total_stock: standard_total_stock = sdt_li[2].total_stock if not standard_total_stock: return for s in sdt_li: total_stock = s.total_stock if total_stock and total_stock != standard_total_stock: today_closing_price = s.today_closing_price * float(total_stock) / float(standard_total_stock) else: today_closing_price = s.today_closing_price trading_data.append({'date': s.date, 'price': today_closing_price, 'total_stock': s.total_stock}) trading_data.reverse() df = DataFrame(trading_data).set_index(['date']) df['short_ema'] = df['price'].ewm(span=kwargs['short_ema']).mean() df['long_ema'] = df['price'].ewm(span=kwargs['long_ema']).mean() df['dif'] = df['short_ema'] - df['long_ema'] df['dea'] = df['dif'].ewm(span=kwargs['dif_ema']).mean() df['macd'] = df['dif'] - df['dea'] today_macd = df.iloc[-1] yestoday_macd = df.iloc[-2] if yestoday_macd['macd'] < 0 < today_macd['macd']: strategy_direction = 'long' strategy_name = 'macd_long_%s_%s_%s' % (kwargs['short_ema'], kwargs['long_ema'], kwargs['dif_ema']) qr = QR( stock_number=stock_number, stock_name=stock_name, date=today_macd.name, strategy_direction=strategy_direction, strategy_name=strategy_name, init_price=today_macd['price'] ) if not check_duplicate(qr): qr.save()
def check_duplicate(sdt): """ 检查某一天的交易数据是否与之前一天完全相同,如果完全相同,则不会保存这些交易数据 为了规避一些法定假日不交易的情况,还有股票停牌的时候,停牌中的数据是不记录的 """ if isinstance(sdt, SDT): trading_date = SDT.objects(stock_number=sdt.stock_number).order_by('-date') if trading_date: latest_sdt = trading_date[0] check_item = ['today_opening_price', 'today_closing_price', 'today_highest_price', 'today_lowest_price', 'increase_amount', 'increase_rate', 'quantity_relative_ratio', 'turnover_rate'] for i in check_item: if sdt[i] != latest_sdt[i]: return False logging.info('%s trading data is same with latest STD, this data will not be saved.' % sdt.stock_number) return True else: return False
def strategy_statistics(strategy_name): all_qr = QR.objects(strategy_name=strategy_name) if not all_qr: print 'Wrong Strategy Name!' return trading_date = SDT.objects(stock_number__startswith='300').distinct('date') trading_date.sort() bt_result = {} for d in trading_date: bt_result[str(d.date())] = back_test_success(strategy_name, d) frame = DataFrame(bt_result) pd.set_option('display.width', 200) pd.set_option('display.max_rows', 400) print frame.reindex(['count', 'one_back_test', 'one_yield_expectation', 'three_back_test', 'three_yield_expectation', 'five_back_test', 'five_yield_expectation']).T pd.set_option('display.width', None) pd.set_option('display.max_rows', None)
def quant_stock(stock_number, short_ma_num=1, long_ma_num=30): strategy_name = 'ma_long_%s_%s' % (short_ma_num, long_ma_num) sdt = SDT.objects(stock_number=stock_number).order_by('-date')[:long_ma_num + 10] if float(sdt[0].increase_rate.replace('%', '')) == 0.0 and float(sdt[0].turnover_rate.replace('%', '')) == 0.0: """ 如果最新一天股票的状态是停牌,跳过 """ return trading_data = [] for i in sdt: """ 去除交易数据里的停牌数据 """ if float(i.increase_rate.replace('%', '')) == 0.0 and float(i.turnover_rate.replace('%', '')) == 0.0: continue else: trading_data.append(i) if len(trading_data) < long_ma_num + 5 or len(trading_data) < short_ma_num + 5: """ 如果交易数据不够,跳过 """ return if short_ma_num <= long_ma_num: strategy_direction = 'long' if float(sdt[0].increase_rate.replace('%', '')) < 0.0: return else: strategy_direction = 'short' if float(sdt[0].increase_rate.replace('%', '')) > 0.0: return short_ma_list = calculate_ma_list(trading_data, short_ma_num, 2) long_ma_list = calculate_ma_list(trading_data, long_ma_num, 2) ma_difference = calculate_ma_difference(short_ma_list, long_ma_list) if ma_difference[0] > 0 > ma_difference[1]: """ 当短期均线向上穿过长期均线的时候 """ save_quant_result(trading_data[0], strategy_name, strategy_direction)
def query_latest_trading(stock_number): sdt = SDT.objects(stock_number=stock_number).order_by('-date')[0] return sdt
skip = 0 notice_data = [] while skip < stocks_count: try: stocks = StockInfo.objects().skip(skip).limit(query_step) except Exception, e: logging.error('Error when query skip %s StockInfo:%s' % (skip, e)) stocks = [] for i in stocks: if i.account_firm and u'瑞华会计师' in i.account_firm: # 过滤瑞华的客户 continue sdt = SDT.objects(Q(stock_number=i.stock_number) & Q(date=datetime.date.today())) if not sdt: # 过滤仍在停牌的票 continue try: notice = collect_event_notice(i.stock_number) except Exception, e: logging.error('Error when collect %s notice: %s' % (i.stock_number, e)) if notice: notice_data += notice skip += query_step if not notice_data: return df = DataFrame(notice_data).sort_values(by=['stock_number', 'date'], ascending=[True, True])\
def check_exists(stock_number, date): cursor = SDT.objects(Q(stock_number=stock_number) & Q(date=date)) if cursor: return True else: return False
def collect_stock_daily_trading(): """ 获取并保存每日股票交易数据 """ url = eastmoney_stock_api data = request_and_handle_data(url) stock_data = data["rank"] for i in stock_data: stock = i.split(",") stock_number = stock[1] stock_name = stock[2] sdt = SDT(stock_number=stock_number, stock_name=stock_name) sdt.yesterday_closed_price = float(stock[3]) sdt.today_opening_price = float(stock[4]) sdt.today_closing_price = float(stock[5]) sdt.today_highest_price = float(stock[6]) sdt.today_lowest_price = float(stock[7]) sdt.turnover_amount = int(stock[8]) sdt.turnover_volume = int(stock[9]) sdt.increase_amount = float(stock[10]) sdt.increase_rate = stock[11] sdt.today_average_price = float(stock[12]) sdt.quantity_relative_ratio = float(stock[22]) sdt.turnover_rate = stock[23] if not check_duplicate(sdt): sdt.save()
def persist_increase(stock_number): try: trading_data = SDT.objects(stock_number=stock_number).order_by('-date')[:3] except Exception, e: logging.error('Query %s SDT failed:%s' % (stock_number, e))