mirror of
https://gitee.com/fasiondog/hikyuu.git
synced 2024-11-30 10:59:43 +08:00
debug pf for not delay sys
This commit is contained in:
parent
4154e0a847
commit
975d764eab
@ -132,7 +132,7 @@ public:
|
||||
/** 获取不同类型K线数据量 */
|
||||
size_t getCount(KQuery::KType dataType = KQuery::DAY) const;
|
||||
|
||||
/** 获取指定日期时刻的市值,即小于等于指定日期的最后一条记录的收盘价 */
|
||||
/** 获取指定日期时刻的市值,即小于等于指定日期的最后一条记录的收盘价, 如果证券已失效,则为0 */
|
||||
price_t getMarketValue(const Datetime&, KQuery::KType) const;
|
||||
|
||||
/**
|
||||
|
@ -266,7 +266,21 @@ SystemWeightList AllocateFundsBase::_adjust_with_running(
|
||||
|
||||
bool trace = getParam<bool>("trace");
|
||||
HKU_INFO_IF(trace, "[AF] {} _adjust_with_running", date);
|
||||
HKU_IF_RETURN(se_list.size() == 0, delay_list);
|
||||
|
||||
// 如果选中列表为空,则需要全部执行清仓,这里不能返回
|
||||
// HKU_IF_RETURN(se_list.size() == 0, delay_list);
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
// 回收所有运行中系统剩余资金,用于重新分配
|
||||
//-----------------------------------------------------------------
|
||||
for (const auto& sys : running_set) {
|
||||
auto sub_tm = sys->getTM();
|
||||
auto sub_cash = sub_tm->currentCash();
|
||||
if (sub_cash > 0.0 && sub_tm->checkout(date, sub_cash)) {
|
||||
m_cash_tm->checkin(date, sub_cash);
|
||||
HKU_INFO_IF(trace, "[AF] Recycle cash: {:<.2f} from {}", sub_cash, sys->name());
|
||||
}
|
||||
}
|
||||
|
||||
// 获取计划分配的资产权重
|
||||
SystemWeightList sw_list = _allocateWeight(date, se_list);
|
||||
@ -281,30 +295,40 @@ SystemWeightList AllocateFundsBase::_adjust_with_running(
|
||||
//-----------------------------------------------------------------
|
||||
// 先将已不在 sw_list 中的运行系统进行清仓,回收可分配资金
|
||||
//-----------------------------------------------------------------
|
||||
std::unordered_set<SYSPtr> running_in_sw_list;
|
||||
std::unordered_set<SYSPtr> running_in_sw_set;
|
||||
for (const auto& sw : sw_list) {
|
||||
if (running_set.find(sw.sys) != running_set.cend()) {
|
||||
running_in_sw_list.insert(sw.sys);
|
||||
running_in_sw_set.insert(sw.sys);
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& sys : running_set) {
|
||||
if (running_in_sw_list.find(sys) == running_in_sw_list.cend()) {
|
||||
if (running_in_sw_set.find(sys) == running_in_sw_set.cend()) {
|
||||
PositionRecord position = sys->getTM()->getPosition(date, sys->getStock());
|
||||
if (sys->getParam<bool>("buy_delay")) {
|
||||
delay_list.emplace_back(sys, MAX_DOUBLE);
|
||||
// 延迟买入的系统,上一调仓日指示买入,可能尚未被执行,需要放入延迟列表中
|
||||
delay_list.emplace_back(sys, position.number);
|
||||
HKU_INFO_IF(trace, "[AF] Clean delay {}", sys->name());
|
||||
|
||||
} else {
|
||||
// 非延迟卖出的系统,立即强制卖出并回收资金
|
||||
auto tr = sys->sellForceOnClose(date, MAX_DOUBLE, PART_ALLOCATEFUNDS);
|
||||
// HKU_DEBUG_IF(trace && tr.isNull(), "[AF] failed to sell: {}", sys->name());
|
||||
auto tr = sys->sellForceOnClose(date, position.number, PART_ALLOCATEFUNDS);
|
||||
if (!tr.isNull()) {
|
||||
auto sub_tm = sys->getTM();
|
||||
auto sub_cash = sub_tm->currentCash();
|
||||
if (sub_tm->checkout(date, sub_cash)) {
|
||||
m_cash_tm->checkin(date, sub_cash);
|
||||
m_tm->addTradeRecord(tr); // 向总账户加入交易记录
|
||||
HKU_INFO_IF(trace, "[AF] Adjust sell: {}, recycle cash: {:<.2f}",
|
||||
HKU_INFO_IF(trace, "[AF] Clean position sell: {}, recycle cash: {:<.2f}",
|
||||
sys->name(), sub_cash);
|
||||
}
|
||||
} else {
|
||||
// 清仓卖出失败情况,也加入到延迟卖出列表中,以便下一交易日可执行
|
||||
PositionRecord position = sys->getTM()->getPosition(date, sys->getStock());
|
||||
if (position.number > 0.0) {
|
||||
delay_list.emplace_back(sys, position.number);
|
||||
HKU_INFO_IF(trace, "[AF] Clean delay {}", sys->name());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -316,8 +340,7 @@ SystemWeightList AllocateFundsBase::_adjust_with_running(
|
||||
// 获取当前总资产市值,计算需保留的资产
|
||||
int precision = m_cash_tm->getParam<int>("precision");
|
||||
FundsRecord funds = m_tm->getFunds(date, m_query.kType());
|
||||
price_t total_funds =
|
||||
funds.cash + funds.market_value + funds.borrow_asset - funds.short_market_value;
|
||||
price_t total_funds = funds.total_assets();
|
||||
price_t reserve_funds = roundEx(total_funds * reserve_percent, precision);
|
||||
|
||||
std::unordered_set<SYSPtr> reduced_running_set; // 缓存已执行过减仓的运行中系统
|
||||
@ -327,34 +350,62 @@ SystemWeightList AllocateFundsBase::_adjust_with_running(
|
||||
TMPtr sub_tm = iter->sys->getTM();
|
||||
const KQuery& query = iter->sys->getTO().getQuery();
|
||||
FundsRecord sub_funds = sub_tm->getFunds(date, query.kType());
|
||||
price_t sub_total_funds = sub_funds.cash + sub_funds.market_value +
|
||||
sub_funds.borrow_asset - sub_funds.short_market_value;
|
||||
price_t sub_total_funds = sub_funds.total_assets();
|
||||
price_t sub_will_funds = total_funds * iter->weight;
|
||||
|
||||
// 如果需要执行减仓
|
||||
if (sub_total_funds > sub_will_funds) {
|
||||
reduced_running_set.insert(iter->sys); // 缓存执行了减仓的系统
|
||||
price_t need_back_funds = sub_total_funds - sub_will_funds;
|
||||
Stock stock = iter->sys->getStock();
|
||||
KRecord krecord = stock.getKRecord(date, query.kType());
|
||||
size_t need_back_shou =
|
||||
size_t(need_back_funds / krecord.closePrice / stock.minTradeNumber());
|
||||
if (need_back_shou > 0) {
|
||||
size_t need_back_num = need_back_shou * stock.minTradeNumber();
|
||||
size_t hold_num = sub_tm->getHoldNumber(date, stock);
|
||||
if (hold_num - need_back_num < stock.minTradeNumber()) {
|
||||
need_back_num = hold_num;
|
||||
}
|
||||
if (iter->sys->getParam<bool>("buy_delay")) {
|
||||
delay_list.emplace_back(iter->sys, need_back_num);
|
||||
} else {
|
||||
auto tr =
|
||||
iter->sys->sellForceOnClose(date, need_back_num, PART_ALLOCATEFUNDS);
|
||||
if (!tr.isNull()) {
|
||||
auto sub_cash = sub_tm->currentCash();
|
||||
if (sub_tm->checkout(date, sub_cash)) {
|
||||
m_cash_tm->checkin(date, sub_cash);
|
||||
m_tm->addTradeRecord(tr); // 向总账户加入交易记录
|
||||
}
|
||||
|
||||
// 获取当前最后的收盘价
|
||||
price_t last_close_price = stock.getMarketValue(date, query.kType());
|
||||
if (last_close_price <= 0.0) {
|
||||
// 证券已失效,无法处理,资产全部损失
|
||||
HKU_WARN_IF(trace, "{} has been delisted!", iter->sys->name());
|
||||
continue;
|
||||
}
|
||||
|
||||
double hold_num = sub_tm->getHoldNumber(date, stock);
|
||||
if (hold_num <= 0.0) {
|
||||
// 实际无持仓
|
||||
continue;
|
||||
}
|
||||
|
||||
// 预期需要卖出的数量
|
||||
double min_num = stock.minTradeNumber();
|
||||
double need_back_num =
|
||||
static_cast<int64_t>(need_back_funds / last_close_price / min_num) * min_num;
|
||||
if (hold_num - need_back_num < min_num) {
|
||||
need_back_num = hold_num;
|
||||
}
|
||||
|
||||
if (need_back_num == 0.0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (iter->sys->getParam<bool>("buy_delay")) {
|
||||
delay_list.emplace_back(iter->sys, need_back_num);
|
||||
HKU_INFO_IF(trace, "[AF] Deduce delay {}, num: {}", iter->sys->name(),
|
||||
need_back_num);
|
||||
|
||||
} else {
|
||||
auto tr = iter->sys->sellForceOnClose(date, need_back_num, PART_ALLOCATEFUNDS);
|
||||
if (!tr.isNull()) {
|
||||
auto sub_cash = sub_tm->currentCash();
|
||||
if (sub_tm->checkout(date, sub_cash)) {
|
||||
m_cash_tm->checkin(date, sub_cash);
|
||||
m_tm->addTradeRecord(tr); // 向总账户加入交易记录
|
||||
HKU_INFO_IF(trace,
|
||||
"[AF] Deduce position {}, sell num: {}, recycle cash: {}",
|
||||
iter->sys->name(), need_back_num, sub_cash);
|
||||
}
|
||||
} else {
|
||||
// 卖出失败的情况,也加入到延迟交易列表中
|
||||
delay_list.emplace_back(iter->sys, need_back_num);
|
||||
HKU_INFO_IF(trace, "[AF] Delay deduce position {}, need sell num: {}",
|
||||
iter->sys->name(), need_back_num);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -383,13 +434,8 @@ SystemWeightList AllocateFundsBase::_adjust_with_running(
|
||||
break;
|
||||
}
|
||||
|
||||
// 计算实际可用的权重
|
||||
price_t current_weight = iter->weight + sum_weight > can_allocate_weight
|
||||
? iter->weight + sum_weight - can_allocate_weight
|
||||
: iter->weight;
|
||||
|
||||
// 系统期望分配的资产额
|
||||
price_t will_funds = roundUp(total_funds * current_weight, precision);
|
||||
price_t will_funds = roundUp(total_funds * iter->weight, precision);
|
||||
|
||||
// 如果该系统是当前运行中系统
|
||||
if (running_set.find(iter->sys) != running_set.cend()) {
|
||||
@ -408,40 +454,35 @@ SystemWeightList AllocateFundsBase::_adjust_with_running(
|
||||
// 未执行过减仓的系统,需要予以相应资金分配
|
||||
if (sub_total_funds >= will_funds) {
|
||||
sum_weight += sub_total_funds / total_funds;
|
||||
|
||||
} else {
|
||||
price_t need_cash = will_funds - sub_total_funds;
|
||||
if (need_cash > can_allocate_cash) {
|
||||
need_cash = can_allocate_cash;
|
||||
}
|
||||
// 如果期望的资金连一手都买不起,则跳过
|
||||
auto krecord = iter->sys->getStock().getKRecord(date, query.kType());
|
||||
if (krecord.isValid() &&
|
||||
need_cash < krecord.closePrice * iter->sys->getStock().minTradeNumber()) {
|
||||
|
||||
// 如果期望的资金连一手都买不起(含退市),则跳过
|
||||
auto last_price = iter->sys->getStock().getMarketValue(date, query.kType());
|
||||
if (need_cash < last_price * iter->sys->getStock().minTradeNumber()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (m_cash_tm->checkout(date, need_cash)) {
|
||||
sub_tm->checkin(date, need_cash);
|
||||
HKU_INFO_IF(trace, "[AF] {} fetched cash: {}", iter->sys->name(),
|
||||
need_cash);
|
||||
|
||||
can_allocate_cash = roundDown(can_allocate_cash - need_cash, precision);
|
||||
// 更新已分配的累积权重
|
||||
sum_weight += (sub_total_funds + need_cash) / total_funds;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
// 非运行中的系统
|
||||
// 计算子账户实际可获取的的资金
|
||||
price_t need_cash = will_funds <= can_allocate_cash ? will_funds : can_allocate_cash;
|
||||
|
||||
// 如果期望的资金连一手都买不起,则跳过
|
||||
const KQuery& query = iter->sys->getTO().getQuery();
|
||||
auto krecord = iter->sys->getStock().getKRecord(date, query.kType());
|
||||
if (krecord.isValid() &&
|
||||
need_cash < krecord.closePrice * iter->sys->getStock().minTradeNumber()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 尝试从资金账户中取出资金存入子账户
|
||||
TMPtr sub_tm = iter->sys->getTM();
|
||||
if (m_cash_tm->checkout(date, need_cash)) {
|
||||
|
@ -72,6 +72,8 @@ void Portfolio::paramChanged() {
|
||||
void Portfolio::reset() {
|
||||
m_real_sys_list.clear();
|
||||
m_running_sys_set.clear();
|
||||
m_failed_sys_map.clear();
|
||||
m_dlist_sys_list.clear();
|
||||
m_delay_adjust_sys_list.clear();
|
||||
m_tmp_selected_list.clear();
|
||||
m_tmp_will_remove_sys.clear();
|
||||
@ -92,7 +94,7 @@ PortfolioPtr Portfolio::clone() {
|
||||
p->m_name = m_name;
|
||||
p->m_query = m_query;
|
||||
p->m_real_sys_list = m_real_sys_list;
|
||||
p->m_need_calculate = m_need_calculate;
|
||||
p->m_need_calculate = true;
|
||||
if (m_se)
|
||||
p->m_se = m_se->clone();
|
||||
if (m_af)
|
||||
@ -195,9 +197,33 @@ void Portfolio::_runMoment(const Datetime& date, bool adjust) {
|
||||
|
||||
bool trace = getParam<bool>("trace");
|
||||
HKU_INFO_IF(trace, "{} ===========================================================", date);
|
||||
HKU_INFO_IF(trace && adjust, "[PF] Position adjustment will be made today.");
|
||||
if (trace && adjust) {
|
||||
HKU_INFO("****************************************************");
|
||||
HKU_INFO("** **");
|
||||
HKU_INFO("** [PF] Position adjustment will be made today. **");
|
||||
HKU_INFO("** **");
|
||||
HKU_INFO("****************************************************");
|
||||
}
|
||||
HKU_INFO_IF(trace, "[PF] current running system size: {}", m_running_sys_set.size());
|
||||
|
||||
//---------------------------------------------------
|
||||
// 检测运行系统中是否存在已退市的证券
|
||||
//---------------------------------------------------
|
||||
for (auto iter = m_running_sys_set.begin(); iter != m_running_sys_set.end(); /*++iter*/) {
|
||||
auto& sys = *iter;
|
||||
if (sys->getStock().getMarketValue(date, m_query.kType()) == 0.0) {
|
||||
auto sub_tm = sys->getTM();
|
||||
auto sub_cash = sub_tm->currentCash();
|
||||
if (sub_cash > 0.0 && sub_tm->checkout(date, sub_cash)) {
|
||||
m_cash_tm->checkin(date, sub_cash);
|
||||
}
|
||||
m_dlist_sys_list.emplace_back(sys);
|
||||
m_running_sys_set.erase(iter++);
|
||||
} else {
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------
|
||||
// 开盘前处理各个子账户、资金账户、总账户之间可能的误差
|
||||
//---------------------------------------------------
|
||||
@ -241,11 +267,53 @@ void Portfolio::_runMoment(const Datetime& date, bool adjust) {
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// 开盘时,优先处理上一交易日确定的需延迟调仓卖出的系统,在开盘时先卖出调整
|
||||
// 开盘时,优先处理上一交易日强制清、减仓失败的系统
|
||||
//----------------------------------------------------------------------
|
||||
// for (auto iter = m_failed_sys_map.begin(); iter != m_failed_sys_map.end();) {
|
||||
// const auto& sys = iter->first;
|
||||
// Stock stk = sys->getStock();
|
||||
// if (date > stk.lastDatetime()) {
|
||||
// // 已退市
|
||||
// HKU_WARN_IF(trace, "{} has been delisted!", sys->name());
|
||||
// m_dlist_sys_list.emplace_back(sys);
|
||||
// m_failed_sys_map.erase(iter++);
|
||||
// continue;
|
||||
// }
|
||||
|
||||
// auto tr = sys->sellForceOnOpen(date, iter->second, PART_PORTFOLIO);
|
||||
// if (!tr.isNull()) {
|
||||
// HKU_INFO_IF(trace, "[PF] Process pre-failed sys: {}", tr);
|
||||
// m_tm->addTradeRecord(tr);
|
||||
|
||||
// // 卖出后,尝试将资金取出转移至影子总账户
|
||||
// TMPtr sub_tm = sys->getTM();
|
||||
// auto sub_cash = sub_tm->currentCash();
|
||||
// if (sub_cash > 0.0 && sub_tm->checkout(date, sub_cash)) {
|
||||
// m_cash_tm->checkin(date, sub_cash);
|
||||
// }
|
||||
|
||||
// m_failed_sys_map.erase(iter++);
|
||||
// continue;
|
||||
|
||||
// } else {
|
||||
// // 如果实际已没有持仓,则将其从失败列表中移除
|
||||
// PositionRecord position = sys->getTM()->getPosition(date, sys->getStock());
|
||||
// if (position.number <= 0.0) {
|
||||
// m_failed_sys_map.erase(iter++);
|
||||
// continue;
|
||||
// }
|
||||
// }
|
||||
|
||||
// ++iter;
|
||||
// }
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// 开盘时,优先处理上一交易日遗留的延迟调仓卖出的系统
|
||||
//----------------------------------------------------------------------
|
||||
HKU_INFO_IF(trace, "[PF] process delay adjust sys, size: {}", m_delay_adjust_sys_list.size());
|
||||
SystemWeightList tmp_continue_adjust_sys_list;
|
||||
for (auto& sys : m_delay_adjust_sys_list) {
|
||||
auto tr = sys.sys->sellForceOnOpen(date, sys.weight, PART_PORTFOLIO);
|
||||
// HKU_DEBUG_IF(trace && tr.isNull(), "[PF] Failed to force sell: {}", sys.sys->name());
|
||||
if (!tr.isNull()) {
|
||||
HKU_INFO_IF(trace, "[PF] Delay adjust sell: {}", tr);
|
||||
m_tm->addTradeRecord(tr);
|
||||
@ -256,15 +324,23 @@ void Portfolio::_runMoment(const Datetime& date, bool adjust) {
|
||||
if (sub_cash > 0.0 && sub_tm->checkout(date, sub_cash)) {
|
||||
m_cash_tm->checkin(date, sub_cash);
|
||||
}
|
||||
|
||||
} else {
|
||||
// 强制卖出失败的情况下,如果当前仍有持仓,则需要下一交易日继续进行处理
|
||||
PositionRecord position = sys.sys->getTM()->getPosition(date, sys.sys->getStock());
|
||||
if (position.number > 0.0) {
|
||||
tmp_continue_adjust_sys_list.emplace_back(sys);
|
||||
// m_failed_sys_map[sys.sys] = sys.weight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 清空,避免循环至下一个非调仓日时被重复处理
|
||||
m_delay_adjust_sys_list.clear();
|
||||
m_delay_adjust_sys_list.swap(tmp_continue_adjust_sys_list);
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// 遍历当前运行中的子系统,如果已没有分配资金和持仓,则回收
|
||||
//---------------------------------------------------------------
|
||||
//---------------------------------------------------------------
|
||||
// 遍历当前运行中的子系统,如果已没有分配资金和持仓,则回收
|
||||
//---------------------------------------------------------------
|
||||
#if 0
|
||||
m_tmp_will_remove_sys.clear();
|
||||
for (auto& running_sys : m_running_sys_set) {
|
||||
Stock stock = running_sys->getStock();
|
||||
@ -278,14 +354,14 @@ void Portfolio::_runMoment(const Datetime& date, bool adjust) {
|
||||
min_cash = krecord.openPrice * stock.minTradeNumber();
|
||||
}
|
||||
|
||||
// 如果系统的剩余资金小于交易一手的资金,则回收资金
|
||||
// 如果系统的剩余资金小于交易一手的资金,则回收资金??? TODO 放到 AF 中进行处理不足一手的
|
||||
if (cash != 0 && cash <= min_cash) {
|
||||
sub_tm->checkout(date, cash);
|
||||
m_cash_tm->checkin(date, cash);
|
||||
HKU_INFO_IF(trace, "Recycle cash ({:<.2f}) from {}, current cash: {}", cash,
|
||||
running_sys->name(), m_cash_tm->currentCash());
|
||||
// 如果已经没有持仓,则回收
|
||||
if (position.number == 0) {
|
||||
if (position.number <= 0.0) {
|
||||
m_tmp_will_remove_sys.emplace_back(running_sys, 0.);
|
||||
HKU_INFO_IF(trace, "[PF] Recycle running sys: {}", running_sys->name());
|
||||
}
|
||||
@ -297,6 +373,7 @@ void Portfolio::_runMoment(const Datetime& date, bool adjust) {
|
||||
HKU_INFO_IF(trace, "Recycling system {}", sub_sys.sys->name());
|
||||
m_running_sys_set.erase(sub_sys.sys);
|
||||
}
|
||||
#endif
|
||||
|
||||
//---------------------------------------------------
|
||||
// 调仓日,进行资金分配调整
|
||||
@ -312,9 +389,18 @@ void Portfolio::_runMoment(const Datetime& date, bool adjust) {
|
||||
}
|
||||
|
||||
// 资产分配算法调整各子系统资产分配
|
||||
m_delay_adjust_sys_list = m_af->adjustFunds(date, m_tmp_selected_list, m_running_sys_set);
|
||||
tmp_continue_adjust_sys_list =
|
||||
m_af->adjustFunds(date, m_tmp_selected_list, m_running_sys_set);
|
||||
|
||||
// 如果选中的系统不在已有列表中,且账户已经被分配了资金,则将其加入运行系统,并执行
|
||||
if (m_delay_adjust_sys_list.empty()) {
|
||||
m_delay_adjust_sys_list.swap(tmp_continue_adjust_sys_list);
|
||||
} else {
|
||||
for (auto& sw : tmp_continue_adjust_sys_list) {
|
||||
m_delay_adjust_sys_list.emplace_back(sw);
|
||||
}
|
||||
}
|
||||
|
||||
// 如果选中的系统不在已有列表中,且账户已经被分配了资金,则将其加入运行系统列表
|
||||
for (auto& sys : m_tmp_selected_list) {
|
||||
if (m_running_sys_set.find(sys.sys) == m_running_sys_set.end()) {
|
||||
if (sys.sys->getTM()->cash(date, m_query.kType()) > 0.0) {
|
||||
|
@ -117,6 +117,8 @@ protected:
|
||||
|
||||
// 用于中间计算的临时数据
|
||||
std::unordered_set<SYSPtr> m_running_sys_set;
|
||||
std::unordered_map<SYSPtr, double> m_failed_sys_map; // 强制卖出失败的系统集合
|
||||
SystemList m_dlist_sys_list; // 因证券退市,无法执行买入的系统(资产全部损失)
|
||||
SystemWeightList m_delay_adjust_sys_list; // 延迟调仓卖出的系统列表
|
||||
SystemWeightList m_tmp_selected_list;
|
||||
SystemWeightList m_tmp_will_remove_sys;
|
||||
|
@ -20,7 +20,7 @@ namespace hku {
|
||||
*/
|
||||
struct HKU_API SystemWeight {
|
||||
SystemPtr sys;
|
||||
price_t weight{1.0};
|
||||
double weight{1.0};
|
||||
|
||||
SystemWeight() = default;
|
||||
SystemWeight(const SystemPtr& sys_, double weight_) : sys(sys_), weight(weight_) {}
|
||||
|
@ -707,11 +707,10 @@ TradeRecord System::_sellForce(const Datetime& date, double num, Part from, bool
|
||||
_getRealSellPrice(krecord.datetime, on_open ? src_krecord.openPrice : src_krecord.closePrice);
|
||||
|
||||
double min_num = m_stock.minTradeNumber();
|
||||
double real_sell_num = num;
|
||||
if (real_sell_num >= position.number) {
|
||||
// 对待卖出的数量进行最小交易单位取整数倍,如果剩余不足最小交易单位,则一次全部卖出
|
||||
double real_sell_num = static_cast<int64_t>(num / min_num) * min_num;
|
||||
if (position.number - real_sell_num < min_num) {
|
||||
real_sell_num = position.number;
|
||||
} else if (min_num > 1) {
|
||||
real_sell_num = static_cast<int64_t>(num / min_num) * min_num;
|
||||
}
|
||||
|
||||
record =
|
||||
|
Loading…
Reference in New Issue
Block a user