Продвинутая лекция по количественной торговле Python

Python анализ данных

Добро пожаловать на подписку«Python Combat — построение системы количественной торговли на основе акций»Буклет, в буклете будут последовательно публиковаться статьи в колонках, связанные с содержанием буклета, которые обеспечат более полное и расширенное введение в соответствующие точки знаний и будут выборочно включены в буклет, облегчая читателям проверку знаний. точки.Эта колонка является продолжением содержания буклета! ! !

предисловие

Исследование количественной торговой стратегии в основном охватывает микро- и макроаспекты, микроаспект в большей степени основан на базовой информации, такой как рыночные цены и позиции транзакций, в качестве объекта исследования модель транзакций. Макроаспект заключается в разработке моделей транзакций на основе большего количества рыночной информации, например, построение моделей транзакций на основе макроэкономических показателей, таких как ИПЦ, ИЦП и эмиссия валюты, в качестве объектов исследования, или использование технологии интеллектуального анализа данных для анализа новостных событий, которые могут вызвать рыночные аномалии. Нестабильные события, чтобы получить возможность торговать.

Мы знаем, что у известных фондовых форумов есть небольшой дом для инвестиций в золото, акции в мире, интернет-фондовый бар Oriental Fortune, фондовый бар Hexun, форум создания, фондовый рынок MACD и т. д. Автор больше использует интернет-фондовый бар Oriental Fortune. В буклете мы рассмотрим случай сканирования рыночных данных отраслевого сектора Dongfang Fortune Net за день и представим принцип и метод веб-краулера.В этом разделе мы расскажем, как сканировать содержимое Dongfang Фортуна Чистый Бар.

Разобрать URL поста

Сначала посетите общие ресурсы Weixing New Materials через браузер и проверьте URL-адрес веб-страницы:http://guba.eastmoney.com/list,002372.html, содержимое веб-страницы показано на следующем рисунке:

Когда мы нажимаем на страницу 2 и страницу 3, текущие URL-адреса выглядят следующим образом:http://guba.eastmoney.com/list,002372_2.html,http://guba.eastmoney.com/list,002372_3.html, поэтому правило URL отдельных акций получается какhttp://guba.eastmoney.com/list, 002372_%d.htmlФорма выражена, правила относительно просты, %d — это номер страницы форума, но эта форма — это URL-адрес, упорядоченный по времени комментария, если URL-адрес упорядочен по времени публикации,http://guba.eastmoney.com/list,002372,f_%d.html.

Пост биржевого бара состоит из двух частей: одна часть представляет собой объявление или официальную новость, опубликованную «Финансовым обозрением» или «Oriental Fortune Network», а другая часть представляет собой сообщение для обсуждения, опубликованное розничными инвесторами, как показано ниже. фигура:

URL сообщения для первогоhttp://guba.eastmoney.com/news,cjpl,902659513.html, URL последнего постаhttp://guba.eastmoney.com/news,002372,902629178.html, оба URL-адреса можно искать в текущем содержимом HTML-файла панели акций, как показано ниже:

Таким образом, основной особенностью сообщений, опубликованных «финансовым комментарием», «Oriental Fortune Network» или розничными инвесторами, является /news.Что касается реализации, мы можем сначала просканировать HTML-содержимое биржевой панели, а затем отфильтровать URL-адрес опубликовать через регулярные выражения.

Ключевой код для чтения HTML-содержимого веб-страниц подробно описан в разделе брошюры «Способ получения данных по отраслевому сектору с помощью сканера». Следует отметить, что urllib, urllib2 и urlparse Python 2 были интегрированы в urllib Python 3. Содержимое urllib и urllib2 Python 2 интегрировано в модуль urllib.request, а urlparse интегрировано в модуль urllib.parse. Содержимое полученного HTML-кода следующее:

Регулярное выражение фильтрует URL-адрес сообщения, используя re.compile и re.findall, код реализации выглядит следующим образом:

pattern = re.compile('/news\S+html',re.S)
news_comment_urls = re.findall(pattern, html_cont.decode('utf-8')) # 非空白字符N次

"""
['/news,cjpl,902659513.html', '/news,cjpl,902684967.html', 
'/news,cjpl,902602349.html', '/news,cjpl,902529812.html', 
'/news,cjpl,857016161.html', '/news,002372,902629178.html', 
'/news,002372,902557935.html', '/news,002372,902533930.html', 
'/news,002372,902519348.html', '/news,002372,902468635.html', 
'/news,002372,902466626.html', '/news,002372,902464127.html', 
 ......
'/news,002372,901168702.html', '/news,002372,901153848.html']
"""

\S+ в регулярном выражении означает соответствие нескольким непробельным символам, а затем использование функции findall для поиска всех совпадающих строк и возврата их в виде списка.

Затем используйте метод urljoin для объединения всего URL-адреса для сканирования содержимого заголовка одного сообщения.Код ключа выглядит следующим образом:

for comment_url in news_comment_urls :
     whole_url = parse.urljoin(page_url, comment_url)
     post_urls.add(whole_url)
return post_urls

Создайте очередь URL-адресов сканера

Затем мы управляем всеми страницами панели акций, которые необходимо просканировать, и URL-адресами сообщений на каждой странице в очереди. Типы последовательностей, хранящихся в Python, это list, tuple, dict и set, различия и характеристики между ними просты: tuple не может изменять элементы в нем, set — это неупорядоченный набор, который автоматически удаляет повторяющиеся элементы, список упорядочен. ; dict — это набор комбинаций ключей и значений. На этот раз мы выбираем list в качестве типа хранения очереди.

Создайте класс target_url_manager, который содержит следующие методы:

  • add_page_urls: проанализируйте HTML-код одной страницы панели акций, чтобы получить URL-адрес публикации страницы.

  • add_pages_urls: создайте очередь и создайте формат двумерного списка для URL-адресов постов всех страниц.

  • has_page_url: определить, пуста ли очередь

  • get_new_url: Публиковать URL для одной страницы за раз

Форма создания очереди следующая:

"""
[['http://guba.eastmoney.com/news,002372,899860502.html',
  'http://guba.eastmoney.com/news,002372,899832598.html',
   ......
  'http://guba.eastmoney.com/news,002372,899947046.html',
  'http://guba.eastmoney.com/news,002372,899897958.html'],
 ['http://guba.eastmoney.com/news,cjpl,903685653.html', 
  'http://guba.eastmoney.com/news,cjpl,903679057.html',
   ......
  'http://guba.eastmoney.com/news,002372,901739862.html',
  'http://guba.eastmoney.com/news,002372,901727241.html']]
['http://guba.eastmoney.com/news,cjpl,903685653.html', 
 'http://guba.eastmoney.com/news,cjpl,903679057.html',
  ......
 'http://guba.eastmoney.com/news,002372,901739862.html',
 'http://guba.eastmoney.com/news,002372,901727241.html']
"""

Полный код можно найти в буклете «Plus Push! Сканер просматривает посты сетевого бара Oriental Fortune».

Проанализируйте содержание поста.

Просканированное содержимое отдельного поста включает три части: время публикации поста, автора и заголовок поста, а именно:

Мы можем извлечь через регулярные выражения, в которых при объединении регулярных выражений нам нужно учитывать, есть ли в HTML-коде повторяющиеся совпадающие ключевые слова. Обычные коды автора и заголовка сообщения следующие: ключевые слова mainbody и zwcontentmain встречаются в тексте только один раз, и степень совпадения высокая. Из-за изменений в HTML-коде веб-сайта выражения необходимо часто корректировать.

Код ключа следующий:

com_cont = re.compile(r'<div id="mainbody">.*?zwconttbn.*?<a.*?<font>(.*?)</font>.*?<div.*?class="zwcontentmain.*?">.*?"zwconttbt">(.*?)</div>.*?social clearfix',re.DOTALL)

Обычный код времени выпуска выглядит следующим образом, и время постепенно и четко извлекается в два этапа.Поскольку поиск заключается в сканировании строки, чтобы найти позицию, в которой совпадает RE, добавьте group(), чтобы вернуть совпадающую строку.

pub_elems = re.search('<div class="zwfbtime">.*?</div>',html_cont2).group()
#<div class="zwfbtime">发表于 2020-02-11 09:54:48 东方财富Android版</div>
pub_time = re.search('\d\d\d\d-\d\d-\d\d',pub_elems).group()
#2020-02-06

Кроме того, сообщения на форуме связаны с текущим трендом цен на акции во времени, а слишком ранние сообщения не имеют справочного эффекта, поэтому необходимо удалять последние сообщения. Мы можем судить о времени, сканируются и сохраняются только посты, опубликованные в течение месяца. Чтобы получить сегодняшнюю дату, используйте datetime.now().date(), а затем сравните ее со временем и датой просканированного сообщения. время во временной форме.

Ключевой код для реализации некоторых ключей выглядит следующим образом:

time_start=datetime.now().date() # 获取日期信息
dt = datetime.strptime(pub_time,"%Y-%m-%d") # 字符串转时间格式
datetime.date(dt)+timedelta(days=30)

После завершения сканирования содержимого одного сообщения мы используем итеративный метод для сканирования всех сообщений. Мы используем двухуровневый итеративный метод, первый слой — это количество страниц, второй слой — это количество сообщений на странице, URL-адрес каждого сообщения хранится в списке, а содержимое сообщений сканируется один раз. по одному через итерацию.

Вот некоторые ключевые коды для достижения:

while self.target_page.has_page_url():
     new_urls = self.target_page.get_new_url() # 获取每个帖子的URL地址队列
     for url in new_urls:
		……

Когда мы обнаруживаем, что сообщение не существует во время сканирования, а информация о сканировании является ненормальной, мы можем использовать try...except... для обработки исключений.

Содержание окончательного просканированного поста показано на следующем рисунке:

Полный код можно найти в буклете «Plus Push! Сканер просматривает посты сетевого бара Oriental Fortune».

Содержимое поста сохраняется в виде txt

Мы можем записать информацию о сканировании в txt-файл. Реализация кода метода open выглядит следующим образом. a+ добавляет запись в конец текста, а не перезаписывает его. Метод codecs.open может указать кодировку для открытия файл и использовать Python. Встроенный открытый открытый файл может записывать только в тип str.

f=codecs.open(name,'a+','utf-8')

Здесь мы создаем класс output_txt, в котором будем реализовывать методы открытия файла, записи файла и закрытия файла соответственно. Код выглядит следующим образом:

class output_txt(object):

    def open_txt(self):
        name = "stock_cont.txt"
        try:
            f = codecs.open(name, 'a+', 'utf-8')
        except Exception as e:
            print("NO TXT")
        return f

    def out_txt(self, f_handle, conts):
        try:
            print("cont",conts)
            f_handle.write(conts)
        except Exception as e:
            print("NO FILE")

    def close_txt(self, f_handle):
        f_handle.close()

Затем вы можете просканировать содержимое поста и записать его в текстовый файл. Код ключа реализации выглядит следующим образом:

file_txt = self.outputer.open_txt()
while self.target_page.has_page_url():
     new_urls = self.target_page.get_new_url() # 获取每个帖子的URL地址队列
     for url in new_urls:
        if time_start <= (self.downloader.find_time(url)+timedelta(days=30)):
           self.outputer.out_txt(file_txt, self.downloader.download(url))
           true_time = true_time + 1
        else:
           error_time = error_time + 1
self.outputer.close_txt(file_txt)

Эффект записи в файл txt следующий:

Суммировать

В этом разделе мы используем методы краулера для получения различного содержимого в сообщениях стоковой панели, так что же для нас значит это содержимое? Мы обнаружили, что некоторые люди поют шорты и вызывают панику, но мы можем проанализировать, имеют ли эти короткие комментарии какое-либо отношение к росту и падению цен на акции, с помощью классификационного анализа. Заинтересованные друзья могут попробовать!

Чтобы узнать больше о количественном трейдинге, подпишитесьбуклетчитать! ! В то же время вы также можете обратить внимание на мой общедоступный аккаунт WeChat [Master Lantern предлагает вам использовать количественную торговлю Python], чтобы узнать больше о количественной торговле Python.