Skip to content

Commit b06210a

Browse files
authored
Merge pull request #302 from fasiondog/feature/block
mysql/sqlite支持自定义板块
2 parents 9355490 + c13b838 commit b06210a

File tree

9 files changed

+205
-25
lines changed

9 files changed

+205
-25
lines changed

hikyuu/draw/drawplot/matplotlib_draw.py

+4
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ def set_mpl_params():
2424
if in_interactive_session():
2525
rcParams['interactive'] = True
2626

27+
if sys.platform == 'darwin':
28+
matplotlib.rcParams['font.sans-serif'] = 'Arial Unicode MS'
29+
return
30+
2731
rcParams['font.family'] = 'sans-serif'
2832
rcParams['axes.unicode_minus'] = False
2933

hikyuu_cpp/hikyuu/StockManager.cpp

+14
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,20 @@ Block StockManager::getBlock(const string& category, const string& name) {
298298
return m_blockDriver ? m_blockDriver->getBlock(category, name) : Block();
299299
}
300300

301+
void StockManager::saveBlock(const Block& blk) {
302+
if (m_blockDriver) {
303+
HKU_CHECK(!blk.category().empty(), "block's category can not be empty!");
304+
HKU_CHECK(!blk.name().empty(), "block's name can not be empty!");
305+
HKU_CHECK(!blk.empty(), "Can't save empty block!");
306+
m_blockDriver->save(blk);
307+
}
308+
}
309+
void StockManager::removeBlock(const string& category, const string& name) {
310+
if (m_blockDriver) {
311+
m_blockDriver->remove(category, name);
312+
}
313+
}
314+
301315
BlockList StockManager::getBlockList(const string& category) {
302316
return m_blockDriver ? m_blockDriver->getBlockList(category) : BlockList();
303317
}

hikyuu_cpp/hikyuu/StockManager.h

+10
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,16 @@ class HKU_API StockManager {
129129
*/
130130
Block getBlock(const string& category, const string& name);
131131

132+
void addBlock(const Block& blk) {
133+
saveBlock(blk);
134+
}
135+
136+
void saveBlock(const Block& blk);
137+
void removeBlock(const string& category, const string& name);
138+
void removeBlock(const Block& blk) {
139+
removeBlock(blk.category(), blk.name());
140+
}
141+
132142
/**
133143
* 获取指定分类的板块列表
134144
* @param category 板块分类

hikyuu_cpp/hikyuu/data_driver/block_info/mysql/MySQLBlockInfoDriver.cpp

+78-9
Original file line numberDiff line numberDiff line change
@@ -6,26 +6,40 @@
66
*/
77

88
#include "hikyuu/utilities/db_connect/mysql/MySQLConnect.h"
9-
#include "hikyuu/utilities/db_connect/TableMacro.h"
9+
#include "hikyuu/utilities/db_connect/DBConnect.h"
1010
#include "MySQLBlockInfoDriver.h"
1111

1212
namespace hku {
1313

14-
struct MySQLBlockTable {
15-
TABLE_BIND4(MySQLBlockTable, block, category, name, market_code, index_code)
14+
struct MySQLBlockView {
15+
TABLE_BIND4(MySQLBlockView, block, category, name, market_code, index_code)
1616
string category;
1717
string name;
1818
string market_code;
1919
string index_code;
2020
};
2121

22+
struct MySQLBlockTable {
23+
TABLE_BIND3(MySQLBlockTable, block, category, name, market_code)
24+
string category;
25+
string name;
26+
string market_code;
27+
};
28+
29+
struct MySQLBlockIndexTable {
30+
TABLE_BIND3(MySQLBlockIndexTable, BlockIndex, category, name, market_code)
31+
string category;
32+
string name;
33+
string market_code;
34+
};
35+
2236
MySQLBlockInfoDriver::~MySQLBlockInfoDriver() {}
2337

2438
bool MySQLBlockInfoDriver::_init() {
2539
return true;
2640
}
2741

28-
void MySQLBlockInfoDriver::load() {
42+
DBConnectPtr MySQLBlockInfoDriver::getConnect() {
2943
Parameter connect_param;
3044
connect_param.set<string>("host", getParamFromOther<string>(m_params, "host", "127.0.0.1"));
3145
connect_param.set<string>("usr", getParamFromOther<string>(m_params, "usr", "root"));
@@ -34,15 +48,19 @@ void MySQLBlockInfoDriver::load() {
3448
string port_str = getParamFromOther<string>(m_params, "port", "3306");
3549
unsigned int port = boost::lexical_cast<unsigned int>(port_str);
3650
connect_param.set<int>("port", port);
37-
MySQLConnect connect(connect_param);
51+
return std::make_shared<MySQLConnect>(connect_param);
52+
}
3853

39-
vector<MySQLBlockTable> records;
40-
connect.batchLoadView(
54+
void MySQLBlockInfoDriver::load() {
55+
auto connect = getConnect();
56+
vector<MySQLBlockView> records;
57+
connect->batchLoadView(
4158
records,
4259
"select a.id, a.category, a.name, a.market_code, b.market_code as "
4360
"index_code from `hku_base`.`block` a left "
4461
"join `hku_base`.`BlockIndex` b on a.category=b.category and a.name = b.name");
4562

63+
std::unique_lock<std::shared_mutex> lock(m_buffer_mutex);
4664
for (auto& record : records) {
4765
auto category_iter = m_buffer.find(record.category);
4866
if (category_iter == m_buffer.end()) {
@@ -59,6 +77,7 @@ void MySQLBlockInfoDriver::load() {
5977

6078
Block MySQLBlockInfoDriver::getBlock(const string& category, const string& name) {
6179
Block ret;
80+
std::shared_lock<std::shared_mutex> lock(m_buffer_mutex);
6281
auto category_iter = m_buffer.find(category);
6382
HKU_IF_RETURN(category_iter == m_buffer.end(), ret);
6483

@@ -71,6 +90,7 @@ Block MySQLBlockInfoDriver::getBlock(const string& category, const string& name)
7190

7291
BlockList MySQLBlockInfoDriver::getBlockList(const string& category) {
7392
BlockList ret;
93+
std::shared_lock<std::shared_mutex> lock(m_buffer_mutex);
7494
auto category_iter = m_buffer.find(category);
7595
HKU_IF_RETURN(category_iter == m_buffer.end(), ret);
7696

@@ -84,6 +104,7 @@ BlockList MySQLBlockInfoDriver::getBlockList(const string& category) {
84104

85105
BlockList MySQLBlockInfoDriver::getBlockList() {
86106
BlockList ret;
107+
std::shared_lock<std::shared_mutex> lock(m_buffer_mutex);
87108
for (auto category_iter = m_buffer.begin(); category_iter != m_buffer.end(); ++category_iter) {
88109
const auto& category_blocks = category_iter->second;
89110
for (auto iter = category_blocks.begin(); iter != category_blocks.end(); ++iter) {
@@ -93,8 +114,56 @@ BlockList MySQLBlockInfoDriver::getBlockList() {
93114
return ret;
94115
}
95116

96-
void MySQLBlockInfoDriver::save(const Block& block) {}
117+
void MySQLBlockInfoDriver::save(const Block& block) {
118+
std::unique_lock<std::shared_mutex> lock(m_buffer_mutex);
119+
auto category_iter = m_buffer.find(block.category());
120+
if (category_iter == m_buffer.end()) {
121+
m_buffer.emplace(block.category(), unordered_map<string, Block>{{block.name(), block}});
122+
} else {
123+
category_iter->second.emplace(block.name(), block);
124+
}
125+
126+
auto connect = getConnect();
127+
AutoTransAction trans(connect);
128+
auto condition = (Field("category") == block.category()) & (Field("name") == block.name());
129+
connect->remove(MySQLBlockView::getTableName(), condition, false);
130+
connect->remove(MySQLBlockIndexTable::getTableName(), condition, false);
131+
132+
if (!block.getIndexStock().isNull()) {
133+
MySQLBlockIndexTable index;
134+
index.category = block.category();
135+
index.name = block.name();
136+
index.market_code = block.getIndexStock().market_code();
137+
connect->save(index, false);
138+
}
139+
140+
for (auto iter = block.begin(); iter != block.end(); ++iter) {
141+
MySQLBlockTable record;
142+
record.category = block.category();
143+
record.name = block.name();
144+
record.market_code = iter->market_code();
145+
connect->save(record, false);
146+
}
147+
}
148+
149+
void MySQLBlockInfoDriver::remove(const string& category, const string& name) {
150+
{
151+
auto connect = getConnect();
152+
AutoTransAction trans(connect);
153+
auto condition = (Field("category") == category) & (Field("name") == name);
154+
connect->remove(MySQLBlockTable::getTableName(), condition, false);
155+
connect->remove(MySQLBlockIndexTable::getTableName(), condition, false);
156+
}
157+
158+
std::unique_lock<std::shared_mutex> lock(m_buffer_mutex);
159+
auto category_iter = m_buffer.find(category);
160+
HKU_IF_RETURN(category_iter == m_buffer.end(), void());
97161

98-
void MySQLBlockInfoDriver::remove(const string& category, const string& name) {}
162+
auto block_iter = category_iter->second.find(name);
163+
HKU_IF_RETURN(block_iter == category_iter->second.end(), void());
164+
165+
category_iter->second.erase(block_iter);
166+
m_buffer.erase(category_iter);
167+
}
99168

100169
} // namespace hku

hikyuu_cpp/hikyuu/data_driver/block_info/mysql/MySQLBlockInfoDriver.h

+5
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
#pragma once
99

10+
#include <mutex>
1011
#include "../../BlockInfoDriver.h"
1112

1213
namespace hku {
@@ -24,8 +25,12 @@ class MySQLBlockInfoDriver : public BlockInfoDriver {
2425
virtual void save(const Block& block) override;
2526
virtual void remove(const string& category, const string& name) override;
2627

28+
private:
29+
DBConnectPtr getConnect();
30+
2731
private:
2832
unordered_map<string, unordered_map<string, Block>> m_buffer;
33+
std::shared_mutex m_buffer_mutex;
2934
};
3035

3136
} // namespace hku

hikyuu_cpp/hikyuu/data_driver/block_info/qianlong/QLBlockInfoDriver.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -190,11 +190,11 @@ BlockList QLBlockInfoDriver::getBlockList() {
190190
}
191191

192192
void QLBlockInfoDriver::save(const Block& block) {
193-
HKU_THROW("Not support save block info!");
193+
HKU_THROW("Not support save block info! You can use ini file to do it!");
194194
}
195195

196196
void QLBlockInfoDriver::remove(const string& category, const string& name) {
197-
HKU_THROW("Not support remove block info!");
197+
HKU_THROW("Not support save block info! You can use ini file to do it!");
198198
}
199199

200200
} /* namespace hku */

hikyuu_cpp/hikyuu/data_driver/block_info/sqlite/SQLiteBlockInfoDriver.cpp

+79-14
Original file line numberDiff line numberDiff line change
@@ -5,39 +5,57 @@
55
* Author: fasiondog
66
*/
77

8+
#include "hikyuu/utilities/db_connect/DBConnect.h"
89
#include "hikyuu/utilities/db_connect/sqlite/SQLiteConnect.h"
9-
#include "hikyuu/utilities/db_connect/TableMacro.h"
1010
#include "SQLiteBlockInfoDriver.h"
1111

1212
namespace hku {
1313

14-
struct SQLiteBlockTable {
15-
TABLE_BIND4(SQLiteBlockTable, block, category, name, market_code, index_code)
14+
struct SQLiteBlockView {
15+
TABLE_BIND4(SQLiteBlockView, block, category, name, market_code, index_code)
1616
string category;
1717
string name;
1818
string market_code;
1919
string index_code;
2020
};
2121

22+
struct SQLiteBlockTable {
23+
TABLE_BIND3(SQLiteBlockTable, block, category, name, market_code)
24+
string category;
25+
string name;
26+
string market_code;
27+
};
28+
29+
struct SQLiteBlockIndexTable {
30+
TABLE_BIND3(SQLiteBlockIndexTable, BlockIndex, category, name, market_code)
31+
string category;
32+
string name;
33+
string market_code;
34+
};
35+
2236
SQLiteBlockInfoDriver::~SQLiteBlockInfoDriver() {}
2337

2438
bool SQLiteBlockInfoDriver::_init() {
2539
string dbname = tryGetParam<string>("db", "");
2640
return !(dbname == "");
2741
}
2842

29-
void SQLiteBlockInfoDriver::load() {
43+
DBConnectPtr SQLiteBlockInfoDriver::getConnect() {
3044
string dbname = tryGetParam<string>("db", "");
31-
HKU_ERROR_IF_RETURN(dbname == "", void(), "Can't get Sqlite3 filename!");
45+
HKU_CHECK(!dbname.empty(), "Can't get Sqlite3 filename!");
3246
HKU_TRACE("SQLITE3: {}", dbname);
47+
return std::make_shared<SQLiteConnect>(m_params);
48+
}
3349

34-
SQLiteConnect connect(m_params);
35-
vector<SQLiteBlockTable> records;
36-
connect.batchLoadView(records,
37-
"select a.id, a.category, a.name, a.market_code, b.market_code as "
38-
"index_code from block a left "
39-
"join BlockIndex b on a.category=b.category and a.name = b.name");
40-
50+
void SQLiteBlockInfoDriver::load() {
51+
vector<SQLiteBlockView> records;
52+
auto connect = getConnect();
53+
connect->batchLoadView(records,
54+
"select a.id, a.category, a.name, a.market_code, b.market_code as "
55+
"index_code from block a left "
56+
"join BlockIndex b on a.category=b.category and a.name = b.name");
57+
58+
std::unique_lock<std::shared_mutex> lock(m_buffer_mutex);
4159
for (auto& record : records) {
4260
auto category_iter = m_buffer.find(record.category);
4361
if (category_iter == m_buffer.end()) {
@@ -54,6 +72,7 @@ void SQLiteBlockInfoDriver::load() {
5472

5573
Block SQLiteBlockInfoDriver::getBlock(const string& category, const string& name) {
5674
Block ret;
75+
std::shared_lock<std::shared_mutex> lock(m_buffer_mutex);
5776
auto category_iter = m_buffer.find(category);
5877
HKU_IF_RETURN(category_iter == m_buffer.end(), ret);
5978

@@ -66,6 +85,7 @@ Block SQLiteBlockInfoDriver::getBlock(const string& category, const string& name
6685

6786
BlockList SQLiteBlockInfoDriver::getBlockList(const string& category) {
6887
BlockList ret;
88+
std::shared_lock<std::shared_mutex> lock(m_buffer_mutex);
6989
auto category_iter = m_buffer.find(category);
7090
HKU_IF_RETURN(category_iter == m_buffer.end(), ret);
7191

@@ -79,6 +99,7 @@ BlockList SQLiteBlockInfoDriver::getBlockList(const string& category) {
7999

80100
BlockList SQLiteBlockInfoDriver::getBlockList() {
81101
BlockList ret;
102+
std::shared_lock<std::shared_mutex> lock(m_buffer_mutex);
82103
for (auto category_iter = m_buffer.begin(); category_iter != m_buffer.end(); ++category_iter) {
83104
const auto& category_blocks = category_iter->second;
84105
for (auto iter = category_blocks.begin(); iter != category_blocks.end(); ++iter) {
@@ -89,11 +110,55 @@ BlockList SQLiteBlockInfoDriver::getBlockList() {
89110
}
90111

91112
void SQLiteBlockInfoDriver::save(const Block& block) {
92-
HKU_THROW("Not support save block info!");
113+
std::unique_lock<std::shared_mutex> lock(m_buffer_mutex);
114+
auto category_iter = m_buffer.find(block.category());
115+
if (category_iter == m_buffer.end()) {
116+
m_buffer.emplace(block.category(), unordered_map<string, Block>{{block.name(), block}});
117+
} else {
118+
category_iter->second.emplace(block.name(), block);
119+
}
120+
121+
auto connect = getConnect();
122+
AutoTransAction trans(connect);
123+
auto condition = (Field("category") == block.category()) & (Field("name") == block.name());
124+
connect->remove(SQLiteBlockView::getTableName(), condition, false);
125+
connect->remove(SQLiteBlockIndexTable::getTableName(), condition, false);
126+
127+
if (!block.getIndexStock().isNull()) {
128+
SQLiteBlockIndexTable index;
129+
index.category = block.category();
130+
index.name = block.name();
131+
index.market_code = block.getIndexStock().market_code();
132+
connect->save(index, false);
133+
}
134+
135+
for (auto iter = block.begin(); iter != block.end(); ++iter) {
136+
SQLiteBlockTable record;
137+
record.category = block.category();
138+
record.name = block.name();
139+
record.market_code = iter->market_code();
140+
connect->save(record, false);
141+
}
93142
}
94143

95144
void SQLiteBlockInfoDriver::remove(const string& category, const string& name) {
96-
HKU_THROW("Not support save block info!");
145+
{
146+
auto connect = getConnect();
147+
AutoTransAction trans(connect);
148+
auto condition = (Field("category") == category) & (Field("name") == name);
149+
connect->remove(SQLiteBlockTable::getTableName(), condition, false);
150+
connect->remove(SQLiteBlockIndexTable::getTableName(), condition, false);
151+
}
152+
153+
std::unique_lock<std::shared_mutex> lock(m_buffer_mutex);
154+
auto category_iter = m_buffer.find(category);
155+
HKU_IF_RETURN(category_iter == m_buffer.end(), void());
156+
157+
auto block_iter = category_iter->second.find(name);
158+
HKU_IF_RETURN(block_iter == category_iter->second.end(), void());
159+
160+
category_iter->second.erase(block_iter);
161+
m_buffer.erase(category_iter);
97162
}
98163

99164
} // namespace hku

0 commit comments

Comments
 (0)