[Mod]improve code style of csv_loader
This commit is contained in:
parent
aa56086d96
commit
af7b433370
54
check.py
54
check.py
@ -1,54 +0,0 @@
|
||||
"""
|
||||
Check code quality for vn.py project.
|
||||
"""
|
||||
|
||||
import logging
|
||||
import os
|
||||
import subprocess
|
||||
from typing import Callable
|
||||
|
||||
logger = logging.Logger(__file__)
|
||||
|
||||
|
||||
def check_and_warning(*args: list, fast_fail: bool = False):
|
||||
"""
|
||||
Run check and show related warning
|
||||
"""
|
||||
passed = True
|
||||
for i in args:
|
||||
if isinstance(i, Callable):
|
||||
print(f"check using {i}")
|
||||
cwd = os.getcwd()
|
||||
res = i()
|
||||
os.chdir(cwd)
|
||||
if not res:
|
||||
passed = False
|
||||
logger.warning("check of %s failed!", i)
|
||||
if not passed and fast_fail:
|
||||
return False
|
||||
return passed
|
||||
|
||||
|
||||
def check_flake8():
|
||||
"""
|
||||
Check code with flake8.
|
||||
"""
|
||||
passed = True
|
||||
try:
|
||||
subprocess.check_call(["python", "-m", "flake8", "./"])
|
||||
except subprocess.SubprocessError:
|
||||
passed = False
|
||||
return passed
|
||||
|
||||
|
||||
def check_all():
|
||||
"""
|
||||
Run check with all tools (only flake8 for now).
|
||||
"""
|
||||
return check_and_warning(check_flake8)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if not check_all():
|
||||
exit(1)
|
||||
exit(0)
|
1
docs/.gitignore
vendored
1
docs/.gitignore
vendored
@ -1 +0,0 @@
|
||||
.doctrees
|
@ -1,6 +1,5 @@
|
||||
# vn.py文档
|
||||
|
||||
|
||||
* [vn.py简介](introduction.md)
|
||||
* [项目安装](install.md)
|
||||
* [基本使用](quickstart.md)
|
||||
|
@ -1,23 +0,0 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) 2019, vn.py Team
|
||||
# This file is distributed under the same license as the vnpy package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2019.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vnpy 2.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-02-13 01:17-0400\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: Babel 2.6.0\n"
|
||||
|
||||
#: ../introduction.md:1
|
||||
msgid "vn.py文档"
|
||||
msgstr ""
|
||||
|
@ -1,22 +0,0 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) 2019, vn.py Team
|
||||
# This file is distributed under the same license as the vnpy package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vnpy 2.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-02-13 01:17-0400\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: ../introduction.md:1
|
||||
msgid "vn.py文档"
|
||||
msgstr ""
|
||||
|
@ -1,23 +0,0 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) 2019, vn.py Team
|
||||
# This file is distributed under the same license as the vnpy package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2019.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vnpy 2.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-02-13 01:17-0400\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: Babel 2.6.0\n"
|
||||
|
||||
#: ../introduction.md:1
|
||||
msgid "vn.py文档"
|
||||
msgstr ""
|
||||
|
@ -1,4 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
sphinx-build -b gettext . locale
|
||||
sphinx-intl update -p locale -l zh-CN -l en
|
@ -11,6 +11,7 @@ from vnpy.gateway.ctp import CtpGateway
|
||||
from vnpy.gateway.tiger import TigerGateway
|
||||
|
||||
from vnpy.app.cta_strategy import CtaStrategyApp
|
||||
from vnpy.app.csv_loader import CsvLoaderApp
|
||||
|
||||
|
||||
def main():
|
||||
@ -27,6 +28,7 @@ def main():
|
||||
main_engine.add_gateway(TigerGateway)
|
||||
|
||||
main_engine.add_app(CtaStrategyApp)
|
||||
main_engine.add_app(CsvLoaderApp)
|
||||
|
||||
main_window = MainWindow(main_engine, event_engine)
|
||||
main_window.showMaximized()
|
||||
|
@ -1,7 +1,7 @@
|
||||
from pathlib import Path
|
||||
|
||||
from vnpy.trader.app import BaseApp
|
||||
from .csv_loader import APP_NAME, CsvLoader
|
||||
from .engine import APP_NAME, CsvLoaderEngine
|
||||
|
||||
|
||||
class CsvLoaderApp(BaseApp):
|
||||
@ -10,7 +10,7 @@ class CsvLoaderApp(BaseApp):
|
||||
app_name = APP_NAME
|
||||
app_module = __module__
|
||||
app_path = Path(__file__).parent
|
||||
display_name = "CSV行情载入器"
|
||||
engine_class = CsvLoader
|
||||
display_name = "CSV加载器"
|
||||
engine_class = CsvLoaderEngine
|
||||
widget_name = "CsvLoaderWidget"
|
||||
icon_name = "csv.ico"
|
||||
|
@ -1,81 +0,0 @@
|
||||
"""
|
||||
Author: nanoric
|
||||
|
||||
Load data from a csv file.
|
||||
|
||||
Differences to 1.9.2:
|
||||
* combine Date column and Time column into one DateTime column
|
||||
|
||||
Sample csv file:
|
||||
|
||||
```csv
|
||||
"DateTime","Open","High","Low","Close","Volume"
|
||||
2010-04-16T09:16:00.000000,3450.0,3488.0,3450.0,3468.0,489
|
||||
2010-04-16T09:17:00.000000,3468.0,3473.8,3467.0,3467.0,302
|
||||
2010-04-16T09:18:00.000000,3467.0,3471.0,3466.0,3467.0,203
|
||||
2010-04-16T09:19:00.000000,3467.0,3468.2,3448.0,3448.0,280
|
||||
2010-04-16T09:20:00.000000,3448.0,3459.0,3448.0,3454.0,250
|
||||
2010-04-16T09:21:00.000000,3454.0,3456.8,3454.0,3456.8,109
|
||||
```
|
||||
|
||||
"""
|
||||
|
||||
import csv
|
||||
from datetime import datetime
|
||||
|
||||
from vnpy.event import EventEngine
|
||||
from vnpy.trader.constant import Exchange, Interval
|
||||
from vnpy.trader.database import DbBarData
|
||||
from vnpy.trader.engine import BaseEngine, MainEngine
|
||||
from vnpy.trader.object import BarData
|
||||
|
||||
APP_NAME = "CsvLoader"
|
||||
|
||||
|
||||
class CsvLoader(BaseEngine):
|
||||
|
||||
def __init__(self, main_engine: MainEngine, event_engine: EventEngine):
|
||||
""""""
|
||||
super().__init__(main_engine, event_engine, APP_NAME)
|
||||
|
||||
self.file_path: str = ''
|
||||
|
||||
self.symbol: str = ""
|
||||
self.exchange: Exchange = Exchange.SSE
|
||||
self.interval: Interval = Interval.MINUTE
|
||||
self.datetime_head: str = ''
|
||||
self.open_head: str = ''
|
||||
self.close_head: str = ''
|
||||
self.low_head: str = ''
|
||||
self.high_head: str = ''
|
||||
self.volume_head: str = ''
|
||||
|
||||
def load(self):
|
||||
""""""
|
||||
symbol = self.symbol
|
||||
exchange = self.exchange
|
||||
interval = self.interval
|
||||
|
||||
datetime_head = self.datetime_head
|
||||
open_head = self.open_head
|
||||
close_head = self.close_head
|
||||
low_head = self.low_head
|
||||
high_head = self.high_head
|
||||
volume_head = self.volume_head
|
||||
|
||||
with open(self.file_path, 'rt') as f:
|
||||
reader = csv.DictReader(f)
|
||||
for item in reader:
|
||||
bar = BarData(
|
||||
'',
|
||||
symbol,
|
||||
exchange,
|
||||
datetime.fromisoformat(item[datetime_head]),
|
||||
interval,
|
||||
item[volume_head],
|
||||
item[open_head],
|
||||
item[high_head],
|
||||
item[low_head],
|
||||
item[close_head],
|
||||
)
|
||||
DbBarData.from_bar(bar).save()
|
99
vnpy/app/csv_loader/engine.py
Normal file
99
vnpy/app/csv_loader/engine.py
Normal file
@ -0,0 +1,99 @@
|
||||
"""
|
||||
Author: nanoric
|
||||
|
||||
Load data from a csv file.
|
||||
|
||||
Differences to 1.9.2:
|
||||
* combine Date column and Time column into one Datetime column
|
||||
|
||||
Sample csv file:
|
||||
|
||||
```csv
|
||||
"Datetime","Open","High","Low","Close","Volume"
|
||||
2010-04-16T09:16:00.000000,3450.0,3488.0,3450.0,3468.0,489
|
||||
2010-04-16T09:17:00.000000,3468.0,3473.8,3467.0,3467.0,302
|
||||
2010-04-16T09:18:00.000000,3467.0,3471.0,3466.0,3467.0,203
|
||||
2010-04-16T09:19:00.000000,3467.0,3468.2,3448.0,3448.0,280
|
||||
2010-04-16T09:20:00.000000,3448.0,3459.0,3448.0,3454.0,250
|
||||
2010-04-16T09:21:00.000000,3454.0,3456.8,3454.0,3456.8,109
|
||||
```
|
||||
|
||||
"""
|
||||
|
||||
import csv
|
||||
from datetime import datetime
|
||||
|
||||
from vnpy.event import EventEngine
|
||||
from vnpy.trader.constant import Exchange, Interval
|
||||
from vnpy.trader.database import DbBarData
|
||||
from vnpy.trader.engine import BaseEngine, MainEngine
|
||||
|
||||
|
||||
APP_NAME = "CsvLoader"
|
||||
|
||||
|
||||
class CsvLoaderEngine(BaseEngine):
|
||||
""""""
|
||||
|
||||
def __init__(self, main_engine: MainEngine, event_engine: EventEngine):
|
||||
""""""
|
||||
super().__init__(main_engine, event_engine, APP_NAME)
|
||||
|
||||
self.file_path: str = ''
|
||||
|
||||
self.symbol: str = ""
|
||||
self.exchange: Exchange = Exchange.SSE
|
||||
self.interval: Interval = Interval.MINUTE
|
||||
self.datetime_head: str = ''
|
||||
self.open_head: str = ''
|
||||
self.close_head: str = ''
|
||||
self.low_head: str = ''
|
||||
self.high_head: str = ''
|
||||
self.volume_head: str = ''
|
||||
|
||||
def load(self,
|
||||
file_path: str,
|
||||
symbol: str,
|
||||
exchange: Exchange,
|
||||
interval: Interval,
|
||||
datetime_head: str,
|
||||
open_head: str,
|
||||
close_head: str,
|
||||
low_head: str,
|
||||
high_head: str,
|
||||
volume_head: str):
|
||||
""""""
|
||||
vt_symbol = f"{symbol}.{exchange.value}"
|
||||
|
||||
start = None
|
||||
end = None
|
||||
count = 0
|
||||
|
||||
with open(file_path, 'rt') as f:
|
||||
reader = csv.DictReader(f)
|
||||
|
||||
for item in reader:
|
||||
db_bar = DbBarData()
|
||||
|
||||
db_bar.symbol = symbol
|
||||
db_bar.exchange = exchange.value
|
||||
db_bar.datetime = datetime.fromisoformat(item[datetime_head])
|
||||
db_bar.interval = interval.value
|
||||
db_bar.volume = item[volume_head]
|
||||
db_bar.open_price = item[open_head]
|
||||
db_bar.high_price = item[high_head]
|
||||
db_bar.low_price = item[low_head]
|
||||
db_bar.close_price = item[close_head]
|
||||
db_bar.vt_symbol = vt_symbol
|
||||
db_bar.gateway_name = "DB"
|
||||
|
||||
db_bar.save()
|
||||
|
||||
# do some statistics
|
||||
count += 1
|
||||
if not start:
|
||||
start = db_bar.datetime
|
||||
|
||||
end = db_bar.datetime
|
||||
|
||||
return start, end, count
|
@ -1 +1 @@
|
||||
from .csv_loader_widget import CsvLoaderWidget
|
||||
from .widget import CsvLoaderWidget
|
||||
|
BIN
vnpy/app/csv_loader/ui/csv.ico
Normal file
BIN
vnpy/app/csv_loader/ui/csv.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 66 KiB |
@ -1,69 +0,0 @@
|
||||
"""
|
||||
Author: nanoric
|
||||
|
||||
UI is designed by Qt Designer. source at csv_loader.ui
|
||||
compile:
|
||||
```
|
||||
pyuic5 csv_loader.ui -o uic/uic_csv_loader.py
|
||||
```
|
||||
"""
|
||||
from gettext import gettext as _
|
||||
|
||||
from PyQt5.QtCore import Qt
|
||||
from PyQt5.QtWidgets import QFileDialog, QMessageBox
|
||||
|
||||
from vnpy.event import EventEngine
|
||||
from vnpy.trader.constant import Exchange, Interval
|
||||
from vnpy.trader.engine import MainEngine
|
||||
from vnpy.trader.ui import QtWidgets
|
||||
from .uic.uic_csv_loader import Ui_CsvLoader
|
||||
from ..csv_loader import CsvLoader
|
||||
|
||||
|
||||
class CsvLoaderWidget(QtWidgets.QWidget):
|
||||
""""""
|
||||
|
||||
def __init__(self, main_engine: MainEngine, event_engine: EventEngine):
|
||||
""""""
|
||||
super().__init__()
|
||||
self.loader = CsvLoader(main_engine, event_engine)
|
||||
self.ui = Ui_CsvLoader()
|
||||
|
||||
self.init_ui()
|
||||
|
||||
def init_ui(self):
|
||||
""""""
|
||||
# someone ask me to disable maximum button
|
||||
self.setWindowFlags(
|
||||
(self.windowFlags() | Qt.CustomizeWindowHint)
|
||||
& ~Qt.WindowMaximizeButtonHint)
|
||||
self.ui.setupUi(self)
|
||||
|
||||
for i in Interval:
|
||||
self.ui.interval_combo.addItem(str(i.name), i)
|
||||
|
||||
for i in Exchange:
|
||||
self.ui.exchange_combo.addItem(str(i.name), i)
|
||||
|
||||
def on_choose_button_pressed(self):
|
||||
""""""
|
||||
result: str = QFileDialog.getOpenFileName(self)
|
||||
filename = result[0]
|
||||
if filename:
|
||||
self.ui.file_edit.setText(filename)
|
||||
|
||||
def on_load_button_pressed(self):
|
||||
""""""
|
||||
self.loader.file_path = self.ui.file_edit.text()
|
||||
self.loader.symbol = self.ui.symbol_edit.text()
|
||||
self.loader.exchange = self.ui.exchange_combo.currentData()
|
||||
self.loader.interval = self.ui.interval_combo.currentData()
|
||||
self.loader.datetime_head = self.ui.datetime_edit.text()
|
||||
self.loader.open_head = self.ui.open_edit.text()
|
||||
self.loader.close_head = self.ui.close_edit.text()
|
||||
self.loader.low_head = self.ui.low_edit.text()
|
||||
self.loader.high_head = self.ui.high_edit.text()
|
||||
self.loader.volume_head = self.ui.volume_edit.text()
|
||||
|
||||
self.loader.load()
|
||||
QMessageBox.information(self, _("载入成功!"), _("CSV行情载入成功!"))
|
90
vnpy/app/csv_loader/ui/widget.py
Normal file
90
vnpy/app/csv_loader/ui/widget.py
Normal file
@ -0,0 +1,90 @@
|
||||
"""
|
||||
Author: nanoric
|
||||
|
||||
UI is designed by Qt Designer. source at csv_loader.ui
|
||||
compile:
|
||||
```
|
||||
pyuic5 csv_loader.ui -o uic/uic_csv_loader.py
|
||||
```
|
||||
"""
|
||||
|
||||
from gettext import gettext as _
|
||||
|
||||
from vnpy.event import EventEngine
|
||||
from vnpy.trader.constant import Exchange, Interval
|
||||
from vnpy.trader.engine import MainEngine
|
||||
from vnpy.trader.ui import QtWidgets, QtCore
|
||||
|
||||
from .uic.uic_csv_loader import Ui_CsvLoader
|
||||
from ..engine import APP_NAME
|
||||
|
||||
|
||||
class CsvLoaderWidget(QtWidgets.QWidget):
|
||||
""""""
|
||||
|
||||
def __init__(self, main_engine: MainEngine, event_engine: EventEngine):
|
||||
""""""
|
||||
super().__init__()
|
||||
|
||||
self.engine = main_engine.get_engine(APP_NAME)
|
||||
|
||||
self.init_ui()
|
||||
|
||||
def init_ui(self):
|
||||
""""""
|
||||
self.setWindowFlags(
|
||||
(self.windowFlags() | QtCore.Qt.CustomizeWindowHint)
|
||||
& ~QtCore.Qt.WindowMaximizeButtonHint)
|
||||
|
||||
self.ui = Ui_CsvLoader()
|
||||
self.ui.setupUi(self)
|
||||
|
||||
for i in Interval:
|
||||
self.ui.interval_combo.addItem(str(i.name), i)
|
||||
|
||||
for i in Exchange:
|
||||
self.ui.exchange_combo.addItem(str(i.name), i)
|
||||
|
||||
def on_choose_button_pressed(self):
|
||||
""""""
|
||||
result: str = QtWidgets.QFileDialog.getOpenFileName(self)
|
||||
filename = result[0]
|
||||
if filename:
|
||||
self.ui.file_edit.setText(filename)
|
||||
|
||||
def on_load_button_pressed(self):
|
||||
""""""
|
||||
file_path = self.ui.file_edit.text()
|
||||
symbol = self.ui.symbol_edit.text()
|
||||
exchange = self.ui.exchange_combo.currentData()
|
||||
interval = self.ui.interval_combo.currentData()
|
||||
datetime_head = self.ui.datetime_edit.text()
|
||||
open_head = self.ui.open_edit.text()
|
||||
low_head = self.ui.low_edit.text()
|
||||
high_head = self.ui.high_edit.text()
|
||||
close_head = self.ui.close_edit.text()
|
||||
volume_head = self.ui.volume_edit.text()
|
||||
|
||||
start, end, count = self.engine.load(
|
||||
file_path,
|
||||
symbol,
|
||||
exchange,
|
||||
interval,
|
||||
datetime_head,
|
||||
open_head,
|
||||
high_head,
|
||||
low_head,
|
||||
close_head,
|
||||
volume_head
|
||||
)
|
||||
|
||||
msg = f"""
|
||||
CSV载入成功
|
||||
代码:{symbol}
|
||||
交易所:{exchange.value}
|
||||
周期:{interval.value}
|
||||
起始:{start}
|
||||
结束:{end}
|
||||
总数量:{count}
|
||||
"""
|
||||
QtWidgets.QMessageBox.information(self, _("载入成功!"), msg)
|
Loading…
Reference in New Issue
Block a user