2015-01-07 01:26:14 +08:00
|
|
|
/*
|
|
|
|
* MoneyManagerBase.cpp
|
|
|
|
*
|
|
|
|
* Created on: 2013-3-3
|
|
|
|
* Author: fasiondog
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "MoneyManagerBase.h"
|
|
|
|
|
|
|
|
namespace hku {
|
|
|
|
|
2019-11-10 23:31:41 +08:00
|
|
|
HKU_API std::ostream& operator<<(std::ostream& os, const MoneyManagerBase& mm) {
|
2015-01-07 01:26:14 +08:00
|
|
|
os << "MoneyManager(" << mm.name() << ", " << mm.getParameter() << ")";
|
|
|
|
return os;
|
|
|
|
}
|
|
|
|
|
2019-11-10 23:31:41 +08:00
|
|
|
HKU_API std::ostream& operator<<(std::ostream& os, const MoneyManagerPtr& mm) {
|
2015-01-07 01:26:14 +08:00
|
|
|
if (mm) {
|
|
|
|
os << *mm;
|
|
|
|
} else {
|
|
|
|
os << "MoneyManager(NULL)";
|
|
|
|
}
|
|
|
|
|
|
|
|
return os;
|
|
|
|
}
|
|
|
|
|
2019-11-10 23:31:41 +08:00
|
|
|
MoneyManagerBase::MoneyManagerBase() : m_name("MoneyManagerBase") {
|
2016-05-03 02:44:03 +08:00
|
|
|
setParam<bool>("auto-checkin", false);
|
2018-01-11 02:54:36 +08:00
|
|
|
setParam<int>("max-stock", 20000);
|
|
|
|
setParam<bool>("disable_ev_force_clean_position", false);
|
|
|
|
setParam<bool>("disable_cn_force_clean_position", false);
|
2016-04-28 02:39:49 +08:00
|
|
|
}
|
|
|
|
|
2019-11-10 23:31:41 +08:00
|
|
|
MoneyManagerBase::MoneyManagerBase(const string& name) : m_name(name) {
|
2016-05-03 02:44:03 +08:00
|
|
|
setParam<bool>("auto-checkin", false);
|
2018-01-11 02:54:36 +08:00
|
|
|
setParam<int>("max-stock", 20000);
|
|
|
|
setParam<bool>("disable_ev_force_clean_position", false);
|
|
|
|
setParam<bool>("disable_cn_force_clean_position", false);
|
2015-01-07 01:26:14 +08:00
|
|
|
}
|
|
|
|
|
2019-11-10 23:31:41 +08:00
|
|
|
MoneyManagerBase::~MoneyManagerBase() {}
|
2015-01-07 01:26:14 +08:00
|
|
|
|
2019-11-10 23:31:41 +08:00
|
|
|
void MoneyManagerBase::buyNotify(const TradeRecord&) {}
|
2015-01-07 01:26:14 +08:00
|
|
|
|
2019-11-10 23:31:41 +08:00
|
|
|
void MoneyManagerBase::sellNotify(const TradeRecord&) {}
|
2015-01-07 01:26:14 +08:00
|
|
|
|
|
|
|
MoneyManagerPtr MoneyManagerBase::clone() {
|
2018-01-14 15:40:07 +08:00
|
|
|
MoneyManagerPtr p;
|
|
|
|
try {
|
|
|
|
p = _clone();
|
2019-11-10 23:31:41 +08:00
|
|
|
} catch (...) {
|
2019-06-16 19:06:06 +08:00
|
|
|
HKU_ERROR("Subclass _clone failed!");
|
2018-01-14 15:40:07 +08:00
|
|
|
p = MoneyManagerPtr();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!p || p.get() == this) {
|
2019-11-10 23:31:41 +08:00
|
|
|
HKU_ERROR("Failed clone! Will use self-ptr!");
|
2018-01-14 15:40:07 +08:00
|
|
|
return shared_from_this();
|
|
|
|
}
|
|
|
|
|
2015-01-07 01:26:14 +08:00
|
|
|
p->m_params = m_params;
|
|
|
|
p->m_name = m_name;
|
2019-11-10 23:31:41 +08:00
|
|
|
// p->m_tm = m_tm;
|
2016-05-18 02:03:29 +08:00
|
|
|
p->m_query = m_query;
|
2015-01-07 01:26:14 +08:00
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
2020-05-12 00:26:29 +08:00
|
|
|
double MoneyManagerBase ::getSellNumber(const Datetime& datetime, const Stock& stock, price_t price,
|
2019-11-10 23:31:41 +08:00
|
|
|
price_t risk, SystemPart from) {
|
2020-11-22 18:34:37 +08:00
|
|
|
HKU_ERROR_IF_RETURN(!m_tm, 0.0,
|
|
|
|
"m_tm is null! Datetime({}) Stock({}) price({:<.4f}) risk({:<.2f})",
|
|
|
|
datetime, stock.market_code(), price, risk);
|
2016-04-03 00:08:31 +08:00
|
|
|
|
2018-01-11 02:54:36 +08:00
|
|
|
if (PART_ENVIRONMENT == from) {
|
2020-11-22 18:34:37 +08:00
|
|
|
//强制全部卖出
|
|
|
|
HKU_IF_RETURN(!getParam<bool>("disable_ev_force_clean_position"), MAX_DOUBLE);
|
2018-01-11 02:54:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (PART_CONDITION == from) {
|
2020-11-22 18:34:37 +08:00
|
|
|
HKU_IF_RETURN(!getParam<bool>("disable_cn_force_clean_position"), MAX_DOUBLE);
|
2016-04-03 00:08:31 +08:00
|
|
|
}
|
|
|
|
|
2020-11-22 18:34:37 +08:00
|
|
|
HKU_IF_RETURN(risk <= 0.0, 0.0);
|
2019-11-10 23:31:41 +08:00
|
|
|
return _getSellNumber(datetime, stock, price, risk, from);
|
2016-04-03 00:08:31 +08:00
|
|
|
}
|
|
|
|
|
2020-05-12 00:26:29 +08:00
|
|
|
double MoneyManagerBase ::getBuyNumber(const Datetime& datetime, const Stock& stock, price_t price,
|
2019-11-10 23:31:41 +08:00
|
|
|
price_t risk, SystemPart from) {
|
2020-11-22 18:34:37 +08:00
|
|
|
HKU_ERROR_IF_RETURN(!m_tm, 0.0,
|
|
|
|
"m_tm is null! Datetime({}) Stock({}) price({:<.3f}) risk({:<.2f})",
|
|
|
|
datetime, stock.market_code(), price, risk);
|
|
|
|
HKU_ERROR_IF_RETURN(stock.isNull(), 0.0, "stock is Null!");
|
2015-01-07 01:26:14 +08:00
|
|
|
|
2020-11-22 18:34:37 +08:00
|
|
|
HKU_ERROR_IF_RETURN(
|
|
|
|
risk <= 0.0, 0.0,
|
|
|
|
"risk is zero! Datetime({}) Stock({}) price({:<.3f}) risk({:<.2f}) Part({})", datetime,
|
|
|
|
stock.market_code(), price, risk, getSystemPartName(from));
|
2016-04-03 00:08:31 +08:00
|
|
|
|
2020-11-22 18:34:37 +08:00
|
|
|
HKU_TRACE_IF_RETURN(m_tm->getStockNumber() >= getParam<int>("max-stock"), 0.0,
|
|
|
|
"Ignore! TM had max-stock number!");
|
2016-07-09 22:37:42 +08:00
|
|
|
|
2020-05-12 00:26:29 +08:00
|
|
|
double n = _getBuyNumber(datetime, stock, price, risk, from);
|
|
|
|
double min_trade = stock.minTradeNumber();
|
2019-11-10 23:31:41 +08:00
|
|
|
|
2019-02-24 19:38:17 +08:00
|
|
|
if (n < min_trade) {
|
2019-06-16 17:56:34 +08:00
|
|
|
HKU_TRACE("Ignore! Is less than the minimum number of transactions({})", min_trade);
|
2016-05-03 02:44:03 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//转换为最小交易量的整数倍
|
2020-05-12 00:26:29 +08:00
|
|
|
n = long(n / min_trade) * min_trade;
|
|
|
|
double max_trade = stock.maxTradeNumber();
|
2016-05-03 02:44:03 +08:00
|
|
|
|
2019-02-24 19:38:17 +08:00
|
|
|
if (n > max_trade) {
|
|
|
|
n = max_trade;
|
2019-06-16 17:56:34 +08:00
|
|
|
HKU_INFO("Over stock.maxTradeNumber({})!", max_trade);
|
2016-05-16 01:45:01 +08:00
|
|
|
}
|
|
|
|
|
2016-05-03 02:44:03 +08:00
|
|
|
//在现金不足时,自动补充存入现金
|
|
|
|
if (getParam<bool>("auto-checkin")) {
|
|
|
|
price_t cash = m_tm->currentCash();
|
|
|
|
CostRecord cost = m_tm->getBuyCost(datetime, stock, price, n);
|
2018-04-25 02:43:55 +08:00
|
|
|
int precision = m_tm->precision();
|
|
|
|
price_t money = roundUp(price * n * stock.unit() + cost.total, precision);
|
2016-05-03 02:44:03 +08:00
|
|
|
if (money > cash) {
|
2018-04-25 02:43:55 +08:00
|
|
|
m_tm->checkin(datetime, roundUp(money - cash, precision));
|
2016-05-03 02:44:03 +08:00
|
|
|
}
|
2019-02-24 19:38:17 +08:00
|
|
|
} else {
|
|
|
|
CostRecord cost = m_tm->getBuyCost(datetime, stock, price, n);
|
|
|
|
price_t need_cash = n * price + cost.total;
|
|
|
|
price_t current_cash = m_tm->currentCash();
|
|
|
|
while (n > min_trade && need_cash > current_cash) {
|
|
|
|
n = n - min_trade;
|
|
|
|
cost = m_tm->getBuyCost(datetime, stock, price, n);
|
|
|
|
need_cash = n * price + cost.total;
|
|
|
|
}
|
|
|
|
n = need_cash > current_cash ? 0 : n;
|
2016-05-03 02:44:03 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return n;
|
2016-04-03 00:08:31 +08:00
|
|
|
}
|
|
|
|
|
2020-05-12 00:26:29 +08:00
|
|
|
double MoneyManagerBase ::getSellShortNumber(const Datetime& datetime, const Stock& stock,
|
2019-11-10 23:31:41 +08:00
|
|
|
price_t price, price_t risk, SystemPart from) {
|
2020-11-22 18:34:37 +08:00
|
|
|
HKU_ERROR_IF_RETURN(!m_tm, 0.0,
|
|
|
|
"m_tm is null! Datetime({}) Stock({}) price({:<.3f}) risk({:<.2f})",
|
|
|
|
datetime, stock.market_code(), price, risk);
|
|
|
|
HKU_ERROR_IF_RETURN(risk <= 0.0, 0.0,
|
|
|
|
"risk is zero! Datetime({}) Stock({}) price({:<.3f}) risk({:<.2f})",
|
|
|
|
datetime, stock.market_code(), price, risk);
|
2018-01-11 02:54:36 +08:00
|
|
|
return _getSellShortNumber(datetime, stock, price, risk, from);
|
2016-04-03 00:08:31 +08:00
|
|
|
}
|
|
|
|
|
2020-05-12 00:26:29 +08:00
|
|
|
double MoneyManagerBase ::getBuyShortNumber(const Datetime& datetime, const Stock& stock,
|
2019-11-10 23:31:41 +08:00
|
|
|
price_t price, price_t risk, SystemPart from) {
|
2020-11-22 18:34:37 +08:00
|
|
|
HKU_ERROR_IF_RETURN(!m_tm, 0.0,
|
|
|
|
"m_tm is null! Datetime({}) Stock({}) price({:<.3f}) risk({:<.2f})",
|
|
|
|
datetime, stock.market_code(), price, risk);
|
|
|
|
HKU_ERROR_IF_RETURN(risk <= 0.0, 0.0,
|
|
|
|
"m_tm is null! Datetime({}) Stock({}) price({:<.3f}) risk({:<.2f})",
|
|
|
|
datetime, stock.market_code(), price, risk);
|
2018-01-11 02:54:36 +08:00
|
|
|
return _getBuyShortNumber(datetime, stock, price, risk, from);
|
2016-04-03 00:08:31 +08:00
|
|
|
}
|
|
|
|
|
2020-05-12 00:26:29 +08:00
|
|
|
double MoneyManagerBase::_getSellNumber(const Datetime& datetime, const Stock& stock, price_t price,
|
2019-11-10 23:31:41 +08:00
|
|
|
price_t risk, SystemPart from) {
|
2016-04-03 00:08:31 +08:00
|
|
|
//默认卖出全部
|
2020-05-12 00:26:29 +08:00
|
|
|
return MAX_DOUBLE;
|
2016-04-03 00:08:31 +08:00
|
|
|
}
|
|
|
|
|
2020-05-12 00:26:29 +08:00
|
|
|
double MoneyManagerBase::_getSellShortNumber(const Datetime& datetime, const Stock& stock,
|
2019-11-10 23:31:41 +08:00
|
|
|
price_t price, price_t risk, SystemPart from) {
|
2016-04-03 00:08:31 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-05-12 00:26:29 +08:00
|
|
|
double MoneyManagerBase::_getBuyShortNumber(const Datetime& datetime, const Stock& stock,
|
2019-11-10 23:31:41 +08:00
|
|
|
price_t price, price_t risk, SystemPart from) {
|
2016-04-03 00:08:31 +08:00
|
|
|
return 0;
|
2015-01-07 01:26:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
} /* namespace hku */
|