10小时了,一个回复都没有,甚至只有寥寥无几的浏览,在求助板块发的帖子还被删除了。过于失望
下面是解决方案。果然还是只能自己动手丰衣足食。
为了简化工作量分表的名字都是合约的代号 如'SR2011',同时只考虑了BarData,即除了'db_tick_data'都视为BarData
默认安装位置,修改了自行推导
C:\vnstudio\Lib\site-packages\vnpy\trader\database\database.py
@abstractmethod
def get_newest_bar_data(
self,
symbol: str,
exchange: "Exchange",
interval: "Interval",
collection_name: str = None
) -> Optional["BarData"]:
"""
If there is data in database, return the one with greatest datetime(newest one)
otherwise, return None
"""
pass
@abstractmethod
def get_oldest_bar_data(
self,
symbol: str,
exchange: "Exchange",
interval: "Interval",
collection_name: str = None
) -> Optional["BarData"]:
"""
If there is data in database, return the one with smallest datetime(oldest one)
otherwise, return None
"""
pass
@abstractmethod
def get_newest_tick_data(
self,
symbol: str,
exchange: "Exchange",
collection_name: str = None
) -> Optional["TickData"]:
"""
If there is data in database, return the one with greatest datetime(newest one)
otherwise, return None
"""
pass
@abstractmethod
def get_bar_data_statistics(
self,
symbol: str,
exchange: "Exchange",
collection_name: str = None
) -> List[Dict]:
"""
Return data avaible in database with a list of symbol/exchange/interval/count.
"""
pass
@abstractmethod
def delete_bar_data(
self,
symbol: str,
exchange: "Exchange",
interval: "Interval",
collection_name: str = None
) -> int:
"""
Delete all bar data with given symbol + exchange + interval.
"""
pass
C:\vnstudio\Lib\site-packages\vnpy\trader\database\database_mongo.py
def get_newest_bar_data(
self, symbol: str, exchange: "Exchange", interval: "Interval",collection_name:str=None
) -> Optional["BarData"]:
if collection_name is None:
s=(
DbBarData.objects(
symbol=symbol,
exchange=exchange.value,
interval=interval.value
)
.order_by("-datetime")
.first()
)
else:
with switch_collection(DbBarData, collection_name):
s = (
DbBarData.objects(
symbol=symbol,
exchange=exchange.value,
interval=interval.value
)
.order_by("-datetime")
.first()
)
if s:
return s.to_bar()
return None
def get_oldest_bar_data(
self, symbol: str, exchange: "Exchange", interval: "Interval",collection_name:str=None
) -> Optional["BarData"]:
if collection_name is None:
s = (
DbBarData.objects(
symbol=symbol,
exchange=exchange.value,
interval=interval.value
)
.order_by("+datetime")
.first()
)
else:
with switch_collection(DbBarData, collection_name):
s = (
DbBarData.objects(
symbol=symbol,
exchange=exchange.value,
interval=interval.value
)
.order_by("+datetime")
.first()
)
if s:
return s.to_bar()
return None
def get_newest_tick_data(
self, symbol: str, exchange: "Exchange",collection_name:str=None
) -> Optional["TickData"]:
if collection_name is None:
s = (
DbTickData.objects(symbol=symbol, exchange=exchange.value)
.order_by("-datetime")
.first()
)
else:
with switch_collection(DbTickData, collection_name):
s = (
DbTickData.objects(symbol=symbol, exchange=exchange.value)
.order_by("-datetime")
.first()
)
if s:
return s.to_tick()
return None
def get_bar_data_statistics(self) -> List:
""""""
if 'db_tick_data' in AllCollectionNames:
AllCollectionNames.remove('db_tick_data')
## print(AllCollectionNames)
s=list()
for i in AllCollectionNames:
with switch_collection(DbBarData,i):
s.extend(
DbBarData.objects.aggregate({
"$group": {
"_id": {
"symbol": "$symbol",
"exchange": "$exchange",
"interval": "$interval",
"collection_name":i,
},
"count": {"$sum": 1}
}
}))
result = []
for d in s:
data = d["_id"]
data["count"] = d["count"]
result.append(data)
return result
def delete_bar_data(
self,
symbol: str,
exchange: "Exchange",
interval: "Interval",
collection_name:str=None
) -> int:
"""
Delete all bar data with given symbol + exchange + interval.
"""
if collection_name is None:
count = DbBarData.objects(
symbol=symbol,
exchange=exchange.value,
interval=interval.value
).delete()
else:
with switch_collection(DbBarData, collection_name):
count = DbBarData.objects(
symbol=symbol,
exchange=exchange.value,
interval=interval.value
).delete()
return count
C:\vnstudio\Lib\site-packages\vnpy\app\data_manager\engine.py
def import_data_from_csv(
self,
file_path: str,
symbol: str,
exchange: Exchange,
interval: Interval,
datetime_head: str,
open_head: str,
high_head: str,
low_head: str,
close_head: str,
volume_head: str,
open_interest_head: str,
datetime_format: str,
OrderBookId:str
) -> Tuple:
""""""
with open(file_path, "rt") as f:
buf = [line.replace("\0", "") for line in f]
reader = csv.DictReader(buf, delimiter=",")
bars = []
start = None
count = 0
for item in reader:
if datetime_format:
dt = datetime.strptime(item[datetime_head], datetime_format)
else:
dt = datetime.fromisoformat(item[datetime_head])
open_interest = item.get(open_interest_head, 0)
bar = BarData(
symbol=symbol,
exchange=exchange,
datetime=dt,
interval=interval,
volume=float(item[volume_head]),
open_price=float(item[open_head]),
high_price=float(item[high_head]),
low_price=float(item[low_head]),
close_price=float(item[close_head]),
open_interest=float(open_interest),
gateway_name="DB",
)
bars.append(bar)
# do some statistics
count += 1
if not start:
start = bar.datetime
# insert into database
database_manager.save_bar_data(bars,OrderBookId)
end = bar.datetime
return start, end, count
def get_bar_data_available(self) -> List[Dict]:
""""""
data = database_manager.get_bar_data_statistics()
for d in data:
oldest_bar = database_manager.get_oldest_bar_data(
d["symbol"], Exchange(d["exchange"]), Interval(d["interval"]),
d['collection_name']
)
d["start"] = oldest_bar.datetime
newest_bar = database_manager.get_newest_bar_data(
d["symbol"], Exchange(d["exchange"]), Interval(d["interval"]),
d['collection_name']
)
d["end"] = newest_bar.datetime
return data
def load_bar_data(
self,
symbol: str,
exchange: Exchange,
interval: Interval,
start: datetime,
end: datetime,
collection_name: str = None,
) -> List[BarData]:
""""""
bars = database_manager.load_bar_data(
symbol,
exchange,
interval,
start,
end,
symbol,
)
return bars
def delete_bar_data(
self,
symbol: str,
exchange: Exchange,
interval: Interval,
collection_name: str = None,
) -> int:
""""""
count = database_manager.delete_bar_data(
symbol,
exchange,
interval,
symbol,
)
return count
C:\vnstudio\Lib\site-packages\vnpy\app\data_manager\ui\widget.py
def import_data(self) -> None:
""""""
dialog = ImportDialog()
n = dialog.exec_()
if n != dialog.Accepted:
return
file_path = dialog.file_edit.text()
symbol = dialog.symbol_edit.text()
OrderBookId= dialog.OrderBookId_edit.text()
exchange = dialog.exchange_combo.currentData()
interval = dialog.interval_combo.currentData()
datetime_head = dialog.datetime_edit.text()
open_head = dialog.open_edit.text()
low_head = dialog.low_edit.text()
high_head = dialog.high_edit.text()
close_head = dialog.close_edit.text()
volume_head = dialog.volume_edit.text()
open_interest_head = dialog.open_interest_edit.text()
datetime_format = dialog.format_edit.text()
start, end, count = self.engine.import_data_from_csv(
file_path,
symbol,
exchange,
interval,
datetime_head,
open_head,
high_head,
low_head,
close_head,
volume_head,
open_interest_head,
datetime_format,
OrderBookId
)
msg = f"\
CSV载入成功\n\
代码:{symbol}\n\
OrderBookId:{OrderBookId}\n\
交易所:{exchange.value}\n\
周期:{interval.value}\n\
起始:{start}\n\
结束:{end}\n\
总数量:{count}\n\
"
QtWidgets.QMessageBox.information(self, "载入成功!", msg)
def __init__(self, parent=None):
""""""
super().__init__()
self.setWindowTitle("从CSV文件导入数据")
self.setFixedWidth(300)
self.setWindowFlags(
(self.windowFlags() | QtCore.Qt.CustomizeWindowHint)
& ~QtCore.Qt.WindowMaximizeButtonHint)
file_button = QtWidgets.QPushButton("选择文件")
file_button.clicked.connect(self.select_file)
load_button = QtWidgets.QPushButton("确定")
load_button.clicked.connect(self.accept)
self.file_edit = QtWidgets.QLineEdit()
self.symbol_edit = QtWidgets.QLineEdit()
self.OrderBookId_edit = QtWidgets.QLineEdit()
self.exchange_combo = QtWidgets.QComboBox()
for i in Exchange:
self.exchange_combo.addItem(str(i.name), i)
self.interval_combo = QtWidgets.QComboBox()
for i in Interval:
if i != Interval.TICK:
self.interval_combo.addItem(str(i.name), i)
self.datetime_edit = QtWidgets.QLineEdit("datetime")
self.open_edit = QtWidgets.QLineEdit("open")
self.high_edit = QtWidgets.QLineEdit("high")
self.low_edit = QtWidgets.QLineEdit("low")
self.close_edit = QtWidgets.QLineEdit("close")
self.volume_edit = QtWidgets.QLineEdit("volume")
self.open_interest_edit = QtWidgets.QLineEdit("open_interest")
self.format_edit = QtWidgets.QLineEdit("%Y-%m-%d %H:%M:%S")
info_label = QtWidgets.QLabel("合约信息")
info_label.setAlignment(QtCore.Qt.AlignCenter)
head_label = QtWidgets.QLabel("表头信息")
head_label.setAlignment(QtCore.Qt.AlignCenter)
format_label = QtWidgets.QLabel("格式信息")
format_label.setAlignment(QtCore.Qt.AlignCenter)
form = QtWidgets.QFormLayout()
form.addRow(file_button, self.file_edit)
form.addRow(QtWidgets.QLabel())
form.addRow(info_label)
form.addRow("代码", self.symbol_edit)
form.addRow("OrderBookId", self.OrderBookId_edit)
form.addRow("交易所", self.exchange_combo)
form.addRow("周期", self.interval_combo)
form.addRow(QtWidgets.QLabel())
form.addRow(head_label)
form.addRow("时间戳", self.datetime_edit)
form.addRow("开盘价", self.open_edit)
form.addRow("最高价", self.high_edit)
form.addRow("最低价", self.low_edit)
form.addRow("收盘价", self.close_edit)
form.addRow("成交量", self.volume_edit)
form.addRow("持仓量", self.open_interest_edit)
form.addRow(QtWidgets.QLabel())
form.addRow(format_label)
form.addRow("时间格式", self.format_edit)
form.addRow(QtWidgets.QLabel())
form.addRow(load_button)
self.setLayout(form)
非常感谢社区精选18 19的作者,我这个操作完全是在他(们)的思路上继续做的,不然我也想不到
另外vnpy写的很赞,虽然没有多少注释,但是变量名把所有的逻辑解释的明明白白,很强
还是希望社区内能互帮互助吧,相逢即是缘,交易已经这么不容易了。