204 lines
6.2 KiB
C#
204 lines
6.2 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace AutoSellerNS
|
|
{
|
|
public class PriceNode
|
|
{
|
|
public int m_iTime;
|
|
public int m_iPrice;
|
|
public int m_iAskPrice;
|
|
public int m_iBidPrice;
|
|
public int m_iAccDealCnt;
|
|
public int m_iDealCnt;
|
|
public double m_dAvg;
|
|
public double m_dSD;
|
|
public double m_dSellLimit;
|
|
public int m_iSellCnt;
|
|
|
|
public override string ToString()
|
|
{
|
|
return $"{m_iPrice}({m_dAvg})";
|
|
}
|
|
}
|
|
|
|
public class STOCK_CUR_ITEM
|
|
{
|
|
public AutoSeller m_Listener = null;
|
|
public CybosHelper m_CybosHelper = null;
|
|
public string m_strCode;
|
|
public string m_strCodeName;
|
|
public DSCBO1Lib.StockCur m_StockCur = null;
|
|
public DSCBO1Lib.StockJpbid m_Jpbid = null;
|
|
public int[] m_aiBidPrice = new int[10];
|
|
public int[] m_aiBidCount = new int[10];
|
|
public int[] m_aiAskPrice = new int[10];
|
|
public int[] m_aiAskCount = new int[10];
|
|
|
|
public int m_iOpenigPrice = 0;
|
|
public int m_iCurPrice = 0;
|
|
public int m_iMaxPrice = 0;
|
|
public int m_iCheckCount = 0;
|
|
|
|
public int m_iTrailingCount = 0;
|
|
|
|
// real time, price time, price
|
|
public List<PriceNode> m_PriceList = new List<PriceNode>();
|
|
public double m_dCheckCountLimit = Config.GetBidCount();
|
|
|
|
int m_iPrevTime = 0;
|
|
|
|
public async void OnRecievedPrice()
|
|
{
|
|
bool bOpeningHour = (m_StockCur.GetHeaderValue(19) == '2');
|
|
m_iCurPrice = m_StockCur.GetHeaderValue(13);
|
|
if (m_iOpenigPrice == 0)
|
|
m_iOpenigPrice = m_iCurPrice;
|
|
int iTime = m_StockCur.GetHeaderValue(18);
|
|
int iConclusionCnt = m_StockCur.GetHeaderValue(17);
|
|
int iAccDealCnt = m_StockCur.GetHeaderValue(9);
|
|
int iDealCnt = m_StockCur.GetHeaderValue(17);
|
|
|
|
int iTimeDiff = 0;
|
|
if (m_iPrevTime > 0)
|
|
iTimeDiff = ((iTime / 10000) * 60 * 60 + ((iTime % 10000) / 100) * 60 + (iTime % 100)) - ((m_iPrevTime / 10000) * 60 * 60 + ((m_iPrevTime % 10000) / 100) * 60 + (m_iPrevTime % 100));
|
|
|
|
if (bOpeningHour == true)
|
|
{
|
|
DateTime RealTime = DateTime.Now;
|
|
int iRealTime = RealTime.Hour * 10000 + RealTime.Minute * 100 + RealTime.Second;
|
|
|
|
List<int> lastNPrice = null;
|
|
lock (m_PriceList)
|
|
{
|
|
if (Config.GetListSize() == 0)
|
|
lastNPrice = m_PriceList.Select(s => s.m_iPrice).ToList();
|
|
else
|
|
lastNPrice = m_PriceList.Skip(Math.Max(0, m_PriceList.Count - (Config.GetListSize() - 1))).Select(s => s.m_iPrice).ToList();
|
|
|
|
lastNPrice.Add(m_iCurPrice);
|
|
}
|
|
|
|
double dAverage = lastNPrice.Average();
|
|
double sumOfSquaresOfDifferences = lastNPrice.Select(val => Math.Pow((val - dAverage) / m_CybosHelper.GetUnitValue(val), 2)).Sum();
|
|
double dStdDev = Math.Sqrt(sumOfSquaresOfDifferences / lastNPrice.Count);
|
|
if (dStdDev >= Config.GetFastSD())
|
|
{
|
|
if (m_iCurPrice >= dAverage)
|
|
m_dCheckCountLimit += Config.GetFastUp();
|
|
else
|
|
m_dCheckCountLimit -= Config.GetFastDown();
|
|
}
|
|
else if (dStdDev <= Config.GetSlowSD())
|
|
{
|
|
if (m_iCurPrice >= dAverage)
|
|
m_dCheckCountLimit += Config.GetSlowUp();
|
|
else
|
|
m_dCheckCountLimit -= Config.GetSlowDown();
|
|
}
|
|
|
|
m_dCheckCountLimit -= iTimeDiff * Config.GetTimeDown();
|
|
|
|
|
|
if (m_iCurPrice > m_iMaxPrice)
|
|
m_iTrailingCount = 0;
|
|
|
|
m_iMaxPrice = Math.Max(m_iCurPrice, m_iMaxPrice);
|
|
|
|
int iAskPrice = m_StockCur.GetHeaderValue(7);
|
|
int iBidPrice = m_StockCur.GetHeaderValue(8);
|
|
|
|
if (m_iCurPrice * iConclusionCnt > Config.GetIgnorePrice())
|
|
{
|
|
if (m_iCurPrice <= iBidPrice)
|
|
m_iCheckCount++;
|
|
else
|
|
m_iCheckCount = 0;
|
|
}
|
|
|
|
if (m_iCheckCount >= m_dCheckCountLimit && m_Listener.IsSelling() == true)
|
|
{
|
|
await m_CybosHelper.SellItem(m_strCode, m_Listener.GetSellableCount(m_strCode), m_aiAskPrice[0]-m_CybosHelper.GetUnitValue(m_iCurPrice));
|
|
Util.Log(Util.LOG_TYPE.SELL, string.Format("[조건 완료 매도] {0} ({1}회) (현재가 {2:n0}원, 최고가 {3:n0}원)",
|
|
m_strCodeName,
|
|
Config.GetBidCount(),
|
|
m_iCurPrice,
|
|
m_iMaxPrice));
|
|
}
|
|
|
|
if (m_iCurPrice < (m_iMaxPrice * (100.0f - Config.GetTrailingRate()) / 100.0f))
|
|
m_iTrailingCount++;
|
|
if (m_iTrailingCount >= Config.GetTrailingCnt() && m_Listener.IsSelling() == true)
|
|
{
|
|
await m_CybosHelper.SellItem(m_strCode, m_Listener.GetSellableCount(m_strCode), m_aiAskPrice[0]-m_CybosHelper.GetUnitValue(m_iCurPrice));
|
|
Util.Log(Util.LOG_TYPE.SELL, string.Format("[트레일링 매도] {0} ({1}% {2}회) (현재가 {3:n0}원, 최고가 {4:n0}원)",
|
|
m_strCodeName,
|
|
Config.GetTrailingRate(),
|
|
Config.GetTrailingCnt(),
|
|
m_iCurPrice,
|
|
m_iMaxPrice));
|
|
}
|
|
|
|
if (iTimeDiff >= Config.GetTimeLimit() && m_Listener.IsSelling() == true)
|
|
{
|
|
await m_CybosHelper.SellItem(m_strCode, m_Listener.GetSellableCount(m_strCode), m_aiAskPrice[0]-m_CybosHelper.GetUnitValue(m_iCurPrice));
|
|
Util.Log(Util.LOG_TYPE.SELL, string.Format("[시간제한 매도] {0} ({1}초) (현재가 {2:n0}원, 최고가 {3:n0}원)",
|
|
m_strCodeName,
|
|
iTimeDiff,
|
|
m_iCurPrice,
|
|
m_iMaxPrice));
|
|
}
|
|
|
|
lock (m_PriceList)
|
|
{
|
|
m_PriceList.Add(new PriceNode
|
|
{
|
|
m_iTime = iTime,
|
|
m_iPrice = m_iCurPrice,
|
|
m_iAskPrice = iAskPrice,
|
|
m_iBidPrice = iBidPrice,
|
|
m_iAccDealCnt = iAccDealCnt,
|
|
m_iDealCnt = iDealCnt,
|
|
m_dAvg = dAverage,
|
|
m_dSD = dStdDev,
|
|
m_dSellLimit = m_dCheckCountLimit,
|
|
m_iSellCnt = m_iCheckCount,
|
|
});
|
|
}
|
|
}
|
|
|
|
m_Listener.OnReceivedCurPrice(m_strCode, m_iCurPrice, m_iMaxPrice, m_dCheckCountLimit, m_iCheckCount, bOpeningHour);
|
|
m_iPrevTime = iTime;
|
|
}
|
|
|
|
public void OnReceivedCall()
|
|
{
|
|
for (int i = 0; i < 5; i++)
|
|
{
|
|
m_aiBidPrice[i] = m_Jpbid.GetHeaderValue(4 + 4 * i);
|
|
m_aiBidCount[i] = m_Jpbid.GetHeaderValue(6 + 4 * i);
|
|
m_aiAskPrice[i] = m_Jpbid.GetHeaderValue(3 + 4 * i);
|
|
m_aiAskCount[i] = m_Jpbid.GetHeaderValue(5 + 4 * i);
|
|
}
|
|
|
|
for (int i = 0; i < 5; i++)
|
|
{
|
|
m_aiBidPrice[i + 5] = m_Jpbid.GetHeaderValue(28 + 4 * i);
|
|
m_aiBidCount[i + 5] = m_Jpbid.GetHeaderValue(30 + 4 * i);
|
|
m_aiAskPrice[i + 5] = m_Jpbid.GetHeaderValue(27 + 4 * i);
|
|
m_aiAskCount[i + 5] = m_Jpbid.GetHeaderValue(29 + 4 * i);
|
|
}
|
|
|
|
m_Listener.OnReceivedCall(m_strCode, 0, m_aiBidPrice, m_aiBidCount, m_aiAskPrice, m_aiAskCount);
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
return $"[{m_strCodeName}:{m_strCode}] {m_iCurPrice}";
|
|
}
|
|
}
|
|
}
|