Skip to content

Commit 8bf7b2e

Browse files
authored
Merge pull request #177 from CleanEngine/feat/realitybot-chart
Feat/realitybot chart
2 parents 581043c + d644daf commit 8bf7b2e

File tree

6 files changed

+60
-63
lines changed

6 files changed

+60
-63
lines changed

src/main/java/com/cleanengine/coin/realitybot/api/ApiScheduler.java

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
package com.cleanengine.coin.realitybot.api;
22

3-
import com.cleanengine.coin.common.annotation.WorkingServerProfile;
43
import com.cleanengine.coin.order.adapter.out.persistentce.asset.AssetRepository;
54
import com.cleanengine.coin.order.domain.Asset;
65
import com.cleanengine.coin.realitybot.domain.APIVWAPState;
76
import com.cleanengine.coin.realitybot.domain.VWAPMetricsRecorder;
87
import com.cleanengine.coin.realitybot.dto.Ticks;
98
import com.cleanengine.coin.realitybot.parser.TickParser;
109
import com.cleanengine.coin.realitybot.service.OrderGenerateService;
10+
import com.cleanengine.coin.realitybot.service.PlatformVWAPService;
1111
import com.cleanengine.coin.realitybot.service.TickServiceManager;
1212
import io.micrometer.core.instrument.MeterRegistry;
1313
import io.micrometer.core.instrument.Timer;
@@ -33,8 +33,9 @@ public class ApiScheduler {
3333
private final CoinoneAPIClient coinoneAPIClient;
3434
private final VWAPMetricsRecorder recorder;
3535
private final MeterRegistry meterRegistry;
36+
private final PlatformVWAPService platformVWAPService;
3637

37-
// @Scheduled(fixedRate = 5000)
38+
// @Scheduled(fixedRate = 5000)
3839
public void MarketAllRequest() throws InterruptedException {
3940
Timer timer = meterRegistry.timer("apischeduler.request.duration");
4041
timer.record(() -> {
@@ -53,24 +54,37 @@ public void MarketDataRequest(String ticker){
5354

5455
APIVWAPState apiVWAPState = tickServiceManager.getService(ticker);
5556
long lastSeqId = lastSequentialIdMap.getOrDefault(ticker,0L);
57+
boolean newTickAdded = false;
5658

5759
//api 중복검사하여 queue에 저장하기
5860
for (int i = gson.size()-1; i >=0 ; i--) {//2차 : 10 - 역순으로 정렬되어 - 순회해야 함.
5961
Ticks ticks = gson.get(i);
6062
if (ticks.getSequential_id() > lastSeqId){ //중복 검증용
6163
apiVWAPState.addTick(ticks);
6264
lastSeqId = Math.max(lastSeqId, ticks.getSequential_id()); //중복 id 갱신
63-
65+
newTickAdded = true;
6466
}
6567
}
6668
lastSequentialIdMap.put(ticker,lastSeqId);
69+
6770
double vwap = apiVWAPState.getVWAP();
6871
double volume = apiVWAPState.getAvgVolumePerOrder();
72+
double platformVwap = platformVWAPService.calculateVWAPbyTrades(ticker,vwap);
73+
double difference = Math.abs((platformVwap - vwap)/vwap);
6974
recorder.recordApiVwap(ticker,vwap);
7075

71-
orderGenerateService.generateOrder(ticker,vwap,volume); //1tick 당 매수/매도 3개씩 제작
76+
if (difference>0.001){
77+
orderGenerateService.generateOrder(ticker,vwap,volume); //1tick 당 매수/매도 3개씩 제작
78+
// log.info("기준치 초과시 {}의 가격 : {} , 볼륨 : {}, 오차 : {}",ticker, vwap, volume, difference);
79+
} else {
80+
if (newTickAdded){
81+
orderGenerateService.generateOrder(ticker,vwap,volume);
82+
// log.info("기준치 이내 {}의 가격 : {} , 볼륨 : {}, 오차 : {}",ticker, vwap, volume, difference);
83+
}
84+
}
85+
86+
7287

73-
// log.info("작동확인 {}의 가격 : {} , 볼륨 : {}",ticker, vwap, volume);
7488
}
7589

7690
/* @Override

src/main/java/com/cleanengine/coin/realitybot/domain/APIVWAPState.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ public void addTick(Ticks tick){
3131

3232
//n초마다 5회 주문 , api 체결 내역에서 10종목씩 비교
3333
public double getAvgVolumePerOrder() {
34-
return calculator.getTotalVolume() / 50;
34+
return calculator.getTotalVolume() / ticksQueue.size();
3535
}//todo 에러 인젝션으로 50일때와 5일때 복귀 속도 알아보기
3636

3737
public double getVWAP(){

src/main/java/com/cleanengine/coin/realitybot/service/OrderGenerateService.java

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -46,19 +46,20 @@ public void generateOrder(String ticker, double apiVWAP, double avgVolume) {//
4646
recorder.recordPlatformVwap(ticker,platformVWAP);
4747
//편차 계산 (vwap 기준)
4848
double trendLineRate = (platformVWAP - apiVWAP)/ apiVWAP;
49+
50+
4951
for(int level : orderLevels) { //1주문당 3회 매수매도 처리
50-
OrderPricePolicy.OrderPrice basePrice = orderPricePolicy.calculatePrice(level,platformVWAP, unitPrice,trendLineRate);
51-
DeviationPricePolicy.AdjustPrice adjustPrice = deviationPricePolicy.adjust(
52-
basePrice.sell(), basePrice.buy(), trendLineRate, apiVWAP, unitPrice);
52+
OrderPricePolicy.OrderPrice basePrice = orderPricePolicy.calculatePrice(level,apiVWAP,platformVWAP, unitPrice);
53+
// DeviationPricePolicy.AdjustPrice adjustPrice = deviationPricePolicy.adjust(basePrice.sell(), basePrice.buy(), trendLineRate, apiVWAP, unitPrice);
5354

5455
double sellVolume = orderVolumePolicy.calculateVolume(avgVolume,trendLineRate,false);
5556
double buyVolume = orderVolumePolicy.calculateVolume(avgVolume,trendLineRate,true);
56-
double sellPrice = adjustPrice.sell();
57-
double buyPrice = adjustPrice.buy();
57+
// double sellPrice = adjustPrice.sell();
58+
// double buyPrice = adjustPrice.buy();
5859

5960

60-
createOrderWithFallback(ticker,false, sellVolume, sellPrice);
61-
createOrderWithFallback(ticker,true, buyVolume, buyPrice);
61+
createOrderWithFallback(ticker,false, sellVolume, basePrice.sell());
62+
createOrderWithFallback(ticker,true, buyVolume, basePrice.buy());
6263

6364
/* DecimalFormat df = new DecimalFormat("#,##0.00");
6465
DecimalFormat dfv = new DecimalFormat("#,###.########");

src/main/java/com/cleanengine/coin/realitybot/vo/DeviationPricePolicy.java

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,16 @@ public class DeviationPricePolicy {
1818

1919
public AdjustPrice adjust(double platformSell,double platformBuy, double trendLineRate, double apiVWAP, double unitPrice){
2020
double deviation = Math.abs(trendLineRate);//음수값 보정
21-
if (deviation <= 0.017){
22-
return new AdjustPrice(platformSell,platformBuy);
21+
// 1% 이내 편차는 조정 없이 원본 가격 반환
22+
if (deviation <= 0.001) { // 0.017 → 0.01로 변경
23+
return new AdjustPrice(platformSell, platformBuy);
2324
}
25+
26+
// 1% 초과 시에만 조정 로직 실행
2427
double weight = getCorrectionWeight(deviation);
25-
// double closeness = 1-weight; // 보간 가중치: 0.7 ~ 1.0 -> 0.5
26-
double closeness; // 보간 가중치: 0.7 ~ 1.0 -> 0.5
27-
if (deviation > 0.07){
28-
closeness = Math.max(0.2, 1 - weight);
29-
} else {
30-
closeness = 0.01;
31-
}
28+
double closeness = (deviation > 0.07)
29+
? Math.max(0.2, 1 - weight)
30+
: 0.01;
3231

3332
// double targetVWAP = (trendLineRate > 0) //만약 closeness 를 0.5 입력시 중간값
3433
// ? apiVWAP + (platformSell - apiVWAP) * closeness // 고평가 → platformSell(25000) → apiVWAP(16000) 사이 가중치 %로 유도

src/main/java/com/cleanengine/coin/realitybot/vo/OrderPricePolicy.java

Lines changed: 22 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -7,55 +7,38 @@ public class OrderPricePolicy {
77
/**
88
* 레벨에 따라 매수/매도 가격을 계산합니다.
99
* @param level 주문 강도 (1~5)
10-
* @param platformVWAP 플랫폼 기준 평균 체결 가격
10+
// * @param platformVWAP 플랫폼 기준 평균 체결 가격
1111
* @param unitPrice 호가 단위
12-
* @param trendLineRate 플랫폼과 API VWAP의 편차율
12+
// * @param trendLineRate 플랫폼과 API VWAP의 편차율
1313
* @return PricePair (매도/매수 가격)
1414
*/
15-
public OrderPrice calculatePrice(int level,
16-
double platformVWAP,
17-
double unitPrice,
18-
double trendLineRate) {
19-
double priceOffset = unitPrice * level;
20-
double sellPrice, buyPrice;
21-
double randomOffset = Math.abs(getRandomOffset(platformVWAP,getDynamicMaxRate(trendLineRate)));
22-
double basePrice = normalizeToUnit(platformVWAP, unitPrice); //기준 가격 (호가 단위 정규화)
15+
public OrderPrice calculatePrice(int level, double apiVWAP, double platformVWAP, double unitPrice) {
16+
double basePrice = normalizeToUnit(apiVWAP, unitPrice);
17+
double targetPrice = normalizeToUnit(platformVWAP, unitPrice);
2318

19+
// 🔥 점진적 접근: API VWAP에서 Platform VWAP로 20% 씩 이동
20+
double convergenceRate = 0.2; // 천천히 접근
21+
double adjustedBase = basePrice + (targetPrice - basePrice) * convergenceRate;
2422

25-
if (level == 1){ //1level일 경우 주문이 겹치도록 설정
26-
//체결을 위해 매수가 올리고, 매도가 내리는 계산 적용
27-
sellPrice = normalizeToUnit(basePrice - randomOffset,unitPrice);
28-
buyPrice = normalizeToUnit(basePrice + randomOffset,unitPrice);
29-
}
30-
//2~3 단계 : orderbook 단위 주문
31-
else {
32-
randomOffset = getRandomOffset(platformVWAP,0.001);
33-
//체결 확률 증가용 코드
34-
sellPrice = normalizeToUnit(platformVWAP + priceOffset - randomOffset,unitPrice);
35-
buyPrice = normalizeToUnit(platformVWAP - priceOffset + randomOffset,unitPrice);
36-
//안정적인 스프레드 유지
37-
// sellPrice = normalizeToUnit(platformVWAP + priceOffset);
38-
// buyPrice = normalizeToUnit(platformVWAP - priceOffset);
23+
double priceOffset = unitPrice * level;
24+
25+
if (level == 1) {
26+
// 1레벨: 조정된 기준가 근처 체결 유도
27+
return new OrderPrice(adjustedBase + priceOffset/2, adjustedBase - priceOffset/2);
28+
} else {
29+
// 2~5레벨: 조정된 기준가 기준 스프레드
30+
return new OrderPrice(adjustedBase + priceOffset, adjustedBase - priceOffset);
3931
}
40-
return new OrderPrice(sellPrice, buyPrice);
4132
}
4233

43-
private double getRandomOffset(double basePrice, double maxRate){
44-
//시장가에 해당하는 호가는 거래 체결 강하게 하기 위함
45-
double percent = (Math.random() * 2-1)*maxRate;
34+
private double getRandomOffset(double basePrice, double maxRate) {
35+
double percent = (Math.random() * 2 - 1) * maxRate;
4636
return basePrice * percent;
4737
}
4838

49-
private double getDynamicMaxRate(double trendLineRate) {
50-
// 편차가 벌어지면 벌어질수록 보정폭 확대
51-
// 5% = 2.51의 가중치
52-
// 11% = 5.51의 가중치
53-
return 0.01 + Math.abs(trendLineRate) * 0.5;
54-
}
55-
56-
private int normalizeToUnit(double price, double unitPrice){ //호가단위로 변환
57-
return (int) ((double)(Math.round(price / unitPrice)) * unitPrice);
39+
private double normalizeToUnit(double price, double unitPrice) {
40+
return Math.round(price / unitPrice) * unitPrice;
5841
}
5942

60-
public record OrderPrice(double sell, double buy){}
61-
}
43+
public record OrderPrice(double sell, double buy) {}
44+
}

src/main/resources/application.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,6 @@ server:
5252
forward-headers-strategy: native
5353

5454
bot-handler:
55-
fixed-rate: 5000 # 5초마다 실행
55+
fixed-rate: 1000 # 5초마다 실행
5656
cron : "0 0 0 * * *" # 매일 자정마다 호가
57-
order-level : 1,2,3,4,5 #오더북 단계 설정 - 주문량 증가
57+
order-level : 1,2 #오더북 단계 설정 - 주문량 증가

0 commit comments

Comments
 (0)