#include "common/pch.h"
|
#include "SellManager.h"
|
#include "../common/NetworkApi.h"
|
#include "../common/JsonUtil.h"
|
#include "ConfigUtil.h"
|
#include "../common/JsonUtil.h"
|
#include "../common/TimeUtil.h"
|
#include <iostream>
|
#include <ctime>
|
|
|
SellSetting* SellManager::getSellSetting(string code)
|
{
|
if (sellSettingMap.find(code) != sellSettingMap.end())
|
{
|
return sellSettingMap[code];
|
}
|
return nullptr;
|
}
|
|
|
|
CodePosition* SellManager::getCodePosition(string code)
|
{
|
if (codePositionMap.find(code) != codePositionMap.end())
|
{
|
return codePositionMap[code];
|
}
|
return nullptr;
|
}
|
|
int SellManager::sell(string code, int sellPriceType)
|
{
|
|
if (sellSettingMap.find(code) == sellSettingMap.end()) {
|
throw wstring(L"ÉÐδÉèÖÃÂô³ö¹æÔò");
|
}
|
//»ñÈ¡³Ö²ÖÐÅÏ¢
|
if (codePositionMap.find(code) == codePositionMap.end()) {
|
throw wstring(L"ÉÐδ»ñÈ¡µ½³Ö²Ö");
|
}
|
|
int money = computeCurrentMoney(code);
|
|
if (money <= 0) {
|
throw wstring(L"¿ÉÂô³öÁ¿Îª0");
|
}
|
|
int volume = sellMoneyToVolume(money, codePositionMap[code]->costPrice);
|
if (volume > codePositionMap[code]->available) {
|
volume = codePositionMap[code]->available;
|
}
|
return sell(code, volume, sellPriceType);
|
}
|
|
int SellManager::sell(string code, int volume, int sellPriceType)
|
{
|
string result = NetworkApi::sell(code, volume, sellPriceType, true);
|
CString msg(code.c_str());
|
msg.Append(L"£º");
|
auto doc = JsonUtil::parseUTF16(result);
|
if (doc.IsObject() && doc.HasMember(L"code")) {
|
if (doc[L"code"] == 0) {
|
if (doc[L"data"].HasMember(L"orderRef")) {
|
msg.Append(_T("Ìá½»Âô³É¹¦"));
|
int orderRef = doc[L"data"][L"orderRef"].GetInt();
|
return orderRef;
|
}
|
else if (doc[L"data"].HasMember(L"orderStatusMsg")) {
|
msg.Append(doc[L"data"][L"orderStatusMsg"].GetString());
|
throw wstring(msg);
|
}
|
}
|
else {
|
if (doc.HasMember(L"msg")) {
|
msg.Append(doc[L"msg"].GetString());
|
throw wstring(msg);
|
}
|
}
|
}
|
else {
|
msg.Append(L"½âÎö½á¹û³ö´í");
|
throw wstring(msg);
|
}
|
|
|
}
|
|
void SellManager::lockVolume(string code, int volume)
|
{
|
}
|
|
void SellManager::unLockVolume(string code)
|
{
|
}
|
|
int SellManager::computeCurrentMoney(string code)
|
{
|
SellSetting* sellSetting = sellSettingMap[code];
|
CodePosition* pos = codePositionMap[code];
|
|
//if (pos->available <= 0) {
|
// return 0;
|
//}
|
|
int sell_count_100 = 0;
|
int available_100 = pos->available / 100;
|
|
if (!sellSetting->lock)
|
{
|
if (sellSetting->setting_mode == SETTING_MODE_RATE) {
|
list<UINT> volumeList = distributeVolume(pos->total / 100, sellSetting->mode1_rate_index);
|
sell_count_100 = computeSellVolume(volumeList, pos->sell_orders);
|
}
|
else {
|
int first_percent = (sellSetting->mode2_first_index + 1) * 10;
|
int second_count = (sellSetting->mode2_left_index + 1);
|
int total_100 = pos->total / 100;
|
|
if (pos->sell_orders.size() == 0) {
|
sell_count_100 = total_100 * first_percent / 100;
|
if (total_100 * first_percent % 100 != 0) {
|
sell_count_100 += 1;
|
}
|
}
|
else {
|
// ×ֲּܳõÈ¥µÚÒ»´ÎµÄ³Ö²Ö
|
list<UINT> volumeList = distributeVolume(total_100 - *(pos->sell_orders.begin()) / 100, second_count);
|
list<UINT>::iterator el = volumeList.begin();
|
advance(el, pos->sell_orders.size() - 1);
|
if (el != volumeList.end()) {
|
sell_count_100 = *el;
|
}
|
else {
|
sell_count_100 = 0;
|
}
|
}
|
}
|
}
|
else {
|
if (sellSetting->lockMoney <= 0) {
|
CString msg = L"Ëø¶¨Á¿´íÎó:";
|
msg.Append(to_wstring(sellSetting->lockMoney).c_str());
|
throw wstring(msg);
|
}
|
// µ±Ç°Ê±¼äÔÚ09:30Ö®ºó£¬Ëø¶¨Ê±¼äÔÚ09:30֮ǰµÄ¾Í·µ»ØÄ¬ÈÏÖµ
|
/*auto nowTime = stoi(TimeUtil::getNowTime("%H%M%S").c_str());
|
if (nowTime >= 93000 && sellSetting->lockTime < 93000) {
|
return ConfigUtil::getSellMoney();
|
}*/
|
return sellSetting->lockMoney;
|
}
|
|
if (sell_count_100 > available_100) {
|
sell_count_100 = available_100;
|
}
|
|
|
return (int) round(sell_count_100 * 100 * pos->costPrice);
|
}
|
|
void SellManager::syncSettingToFile(string code)
|
{
|
|
// ¶ÔÏóתΪjson
|
|
if (sellSettingMap.find(code)== sellSettingMap.end())
|
{
|
return;
|
}
|
|
SellSetting* sellSetting = sellSettingMap[code];
|
auto nowDate = getNowDate();
|
string key = string("sell_setting-").append(nowDate).append("-").append(code);
|
|
rapidjson::StringBuffer buf;
|
rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buf);
|
writer.StartObject();
|
writer.Key("setting_mode");
|
writer.Int(sellSetting->setting_mode);
|
writer.Key("lock");
|
writer.Bool(sellSetting->lock);
|
writer.Key("lockMoney");
|
writer.Int(sellSetting->lockMoney);
|
writer.Key("lockBuy");
|
writer.Bool(sellSetting->lockBuy);
|
writer.Key("lockBuyMoney");
|
writer.Int(sellSetting->lockBuyMoney);
|
writer.Key("mode1_rate_index");
|
writer.Int(sellSetting->mode1_rate_index);
|
writer.Key("mode2_first_index");
|
writer.Int(sellSetting->mode2_first_index);
|
writer.Key("mode2_left_index");
|
writer.Int(sellSetting->mode2_left_index);
|
writer.EndObject();
|
const char* json_content = buf.GetString();
|
ConfigUtil::setStringConfig(key.c_str(), json_content);
|
}
|
|
void SellManager::clearPreSettings()
|
{
|
list<string> keys = ConfigUtil::getKeys();
|
|
auto nowDate = getNowDate();
|
string prefix = string("sell_setting-");
|
string prefix_today = string("sell_setting-").append(nowDate);
|
|
for (list<string>::iterator e = keys.begin(); e != keys.end(); e++) {
|
string key = *e;
|
if (key.find(prefix) == 0 && key.find(prefix_today) < 0) {
|
ConfigUtil::delKey(key);
|
}
|
}
|
}
|
|
|
string SellManager::getNowDate()
|
{
|
std::time_t now = std::time(nullptr);
|
// ʹÓñ¾µØÊ±¼äת»»µ±Ç°Ê±¼ä
|
std::tm currentDate;
|
localtime_s(¤tDate,&now);
|
// ¶¨ÒåÈÕÆÚ¸ñʽ
|
char buffer[80];
|
std::strftime(buffer, sizeof(buffer), "%Y%m%d", ¤tDate);
|
return string(buffer);
|
}
|
|
SellSetting* SellManager::loadSettingFromFile(string code)
|
{
|
|
auto nowDate = getNowDate();
|
string key = string("sell_setting-").append(nowDate).append("-").append(code);
|
try {
|
string result = ConfigUtil::readStringConfig(key.c_str());
|
auto doc = JsonUtil::parseUTF8(result);
|
SellSetting* setting = new SellSetting();
|
setting->lock = doc["lock"].GetBool();
|
setting->lockMoney = doc["lockMoney"].GetInt();
|
setting->lockBuy = doc["lockBuy"].GetBool();
|
setting->lockBuyMoney = doc["lockBuyMoney"].GetInt();
|
setting->setting_mode = doc["setting_mode"].GetInt()==0? SETTING_MODE_RATE: SETTING_MODE_PERCENT;
|
setting->mode2_first_index = doc["mode2_first_index"].GetInt();
|
setting->mode2_left_index = doc["mode2_left_index"].GetInt();
|
setting->mode1_rate_index = doc["mode1_rate_index"].GetInt();
|
return setting;
|
}
|
catch (...) {
|
|
}
|
|
|
|
return nullptr;
|
}
|
|
list<UINT> SellManager::distributeVolume(UINT total, UINT percent)
|
{
|
list<UINT> volumeList;
|
UINT base = total / percent;
|
UINT left = total % percent;
|
for (UINT i = 0; i < percent; i++) {
|
if (i + 1 <= left) {
|
volumeList.push_back(base + 1);
|
}
|
else {
|
volumeList.push_back(base);
|
}
|
}
|
return volumeList;
|
}
|
|
UINT SellManager::computeSellVolume(list<UINT> volumeList, list<int> sell_volumes)
|
{
|
if (sell_volumes.size() >= volumeList.size()) {
|
return 0;
|
}
|
list<UINT>::iterator el = volumeList.begin();
|
advance(el, sell_volumes.size());
|
if (el != volumeList.end()) {
|
return *el;
|
}
|
return 0;
|
}
|
|
|
int SellManager::sellMoneyToVolume(int money, double price)
|
{
|
int volume = ((int)round((money / price) * 100)) / 100;
|
volume = volume < 0 ? 0 : volume;
|
return volume / 100 * 100;
|
}
|
|
void SellManager::init(string code)
|
{
|
// ³õʼ»¯´úÂë
|
if (getSellSetting(code) == nullptr) {
|
SellSetting* setting = loadSettingFromFile(code);
|
if (setting == nullptr) {
|
setting = new SellSetting();
|
setting->lock = true;
|
setting->lockMoney = ConfigUtil::getSellMoney();
|
setting->lockBuy = true;
|
setting->lockTime = stoi(TimeUtil::getNowTime("%H%M%S").c_str());
|
setting->lockBuyMoney = 0;
|
setting->setting_mode = SETTING_MODE_RATE;
|
setting->mode1_rate_index = 4;
|
}
|
sellSettingMap[code] = setting;
|
}
|
|
if (getCodePosition(code) == nullptr) {
|
CodePosition* codePosition = new CodePosition();
|
codePosition->available = 0;
|
codePosition->costPrice = 0.0f;
|
codePosition->total = 0;
|
codePosition->sell_rules_count = 0;
|
codePosition->sell_orders = list<int>();
|
codePositionMap[code] = codePosition;
|
}
|
}
|