gpt4 book ai didi

java - 与币安不同的 EMA(指数移动平均线)

转载 作者:行者123 更新时间:2023-12-05 04:54:31 25 4
gpt4 key购买 nike

我正在使用 Binance JAVA API 编写 Java 程序检索交易对的 1 分钟间隔烛台。使用this Java类,我想计算过去10天的EMA(指数移动平均线)。

Binance JAVA API websocket 实现获取最新的深度事件,其中还包含我用来通过调用 EMA#update 方法更新 EMA 计算的当前收盘价。

但是,我注意到 Binance 图表上显示的 EMA 与我从代码中获得的不对应。此外,我注意到这些值需要一些时间来“稳定”,然后才能给出与 Binance 上显示的值(有些)相同的值。

Output of the program

Values on Binance

我在 TradingView 上找到了 a formula计算 EMA(显示与 Binance 相同的 EMA 值),但这与 EMA 类中使用的不同。然而,即使使用此公式,其值也与 Binance 上的值大不相同。

谁能帮我弄清楚问题是什么以及如何获得相同的值?

更新 1:提供的代码

import java.util.*;
import java.util.stream.Collectors;

import com.binance.api.client.BinanceApiClientFactory;
import com.binance.api.client.BinanceApiRestClient;
import com.binance.api.client.BinanceApiWebSocketClient;
import com.binance.api.client.domain.market.Candlestick;
import com.binance.api.client.domain.market.CandlestickInterval;
import core.util.text.DecimalFormat;
import core.util.text.StringUtil;

public class test_003
{
private Map<Long, Candlestick> candlesticksCache = new TreeMap<>();

private EMA EMA_10;
private EMA EMA_20;

public static void main(String[] pArgs)
{
new test_003();
}

private test_003()
{
Locale.setDefault(Locale.US);

candlesticksCacheExample("ADAUSDT", CandlestickInterval.ONE_MINUTE);
}

private void candlesticksCacheExample(String symbol, CandlestickInterval interval)
{
initializeCandlestickCache(symbol, interval);

startCandlestickEventStreaming(symbol, interval);
}

private void initializeCandlestickCache(String symbol, CandlestickInterval interval)
{
BinanceApiClientFactory factory = BinanceApiClientFactory.newInstance();
BinanceApiRestClient client = factory.newRestClient();

List<Candlestick> candlestickBars_10 = client.getCandlestickBars(symbol.toUpperCase(), interval, Integer.valueOf(11), null, null);
List<Candlestick> candlestickBars_20 = client.getCandlestickBars(symbol.toUpperCase(), interval, Integer.valueOf(21), null, null);

List<Double> closingPriceList_10 = candlestickBars_10.stream().map(c -> Double.valueOf(c.getClose())).collect(Collectors.toList());
List<Double> closingPriceList_20 = candlestickBars_20.stream().map(c -> Double.valueOf(c.getClose())).collect(Collectors.toList());

EMA_10 = new EMA(closingPriceList_10, Integer.valueOf(10));
EMA_20 = new EMA(closingPriceList_20, Integer.valueOf(20));
}

private void startCandlestickEventStreaming(String symbol, CandlestickInterval interval)
{
BinanceApiClientFactory factory = BinanceApiClientFactory.newInstance();
BinanceApiWebSocketClient client = factory.newWebSocketClient();

client.onCandlestickEvent(symbol.toLowerCase(), interval, response -> {
Long openTime = response.getOpenTime();
Candlestick updateCandlestick = candlesticksCache.get(openTime);
if (updateCandlestick == null)
{
// new candlestick
updateCandlestick = new Candlestick();
}

// update candlestick with the stream data
updateCandlestick.setOpenTime(response.getOpenTime());
updateCandlestick.setOpen(response.getOpen());
updateCandlestick.setLow(response.getLow());
updateCandlestick.setHigh(response.getHigh());
updateCandlestick.setClose(response.getClose());
updateCandlestick.setCloseTime(response.getCloseTime());
updateCandlestick.setVolume(response.getVolume());
updateCandlestick.setNumberOfTrades(response.getNumberOfTrades());
updateCandlestick.setQuoteAssetVolume(response.getQuoteAssetVolume());
updateCandlestick.setTakerBuyQuoteAssetVolume(response.getTakerBuyQuoteAssetVolume());
updateCandlestick.setTakerBuyBaseAssetVolume(response.getTakerBuyQuoteAssetVolume());

// Store the updated candlestick in the cache
candlesticksCache.put(openTime, updateCandlestick);

double closingPrice = Double.valueOf(updateCandlestick.getClose());

EMA_10.update(closingPrice);
EMA_20.update(closingPrice);

System.out.println(StringUtil.replacePlaceholders("Closing price: %1 | EMA(10): %2 - EMA(20): %3", response.getClose(),
DecimalFormat.format(EMA_10.get(), "#.#####"),
DecimalFormat.format(EMA_20.get(), "#.#####")));
});
}

public class EMA
{

private double currentEMA;
private final int period;
private final double multiplier;
private final List<Double> EMAhistory;
private final boolean historyNeeded;
private String fileName;


public EMA(List<Double> closingPrices, int period)
{
this(closingPrices, period, false);
}

public EMA(List<Double> closingPrices, int period, boolean historyNeeded)
{
currentEMA = 0;
this.period = period;
this.historyNeeded = historyNeeded;
this.multiplier = 2.0 / (double) (period + 1);
this.EMAhistory = new ArrayList<>();
init(closingPrices);
}

public double get()
{
return currentEMA;
}

public double getTemp(double newPrice)
{
return (newPrice - currentEMA) * multiplier + currentEMA;
}

public void init(List<Double> closingPrices)
{
if (period > closingPrices.size()) return;

//Initial SMA
for (int i = 0; i < period; i++)
{
currentEMA += closingPrices.get(i);
}

currentEMA = currentEMA / (double) period;
if (historyNeeded) EMAhistory.add(currentEMA);
//Dont use latest unclosed candle;
for (int i = period; i < closingPrices.size() - 1; i++)
{
update(closingPrices.get(i));
}
}

public void update(double newPrice)
{
// EMA = (Close - EMA(previousBar)) * multiplier + EMA(previousBar)
currentEMA = (newPrice - currentEMA) * multiplier + currentEMA;

if (historyNeeded) EMAhistory.add(currentEMA);
}

public int check(double newPrice)
{
return 0;
}

public String getExplanation()
{
return null;
}

public List<Double> getEMAhistory()
{
return EMAhistory;
}

public int getPeriod()
{
return period;
}
}
}

更新 2

enter image description here

最佳答案

问题是 onCandlestickEvent 不仅在蜡烛完成时调用,而且实际上每分钟调用多次(每 2 秒左右)。您在 response 中收到的数据涵盖了从打开蜡烛到响应事件时间的时间,无论蜡烛是否完成。

要理解我的意思,您可以将 startCandlestickEventStreaming 方法中的 System.out() 语句替换为以下内容:

System.out.println(response.getOpenTime() + ";" +
response.getEventTime() + ";" +
response.getCloseTime());

您会看到蜡烛的收盘时间实际上是在未来。

为了正确更新您的 EMA,您必须等到蜡烛实际完成。您可以将暂定蜡烛的开盘时间存储在一个成员变量中,检查自上次调用 onCandlestickEvent 以来它是否发生了变化,然后使用蜡烛的最终收盘值更新您的 EMA:

client.onCandlestickEvent(symbol.toLowerCase(), interval, response -> {
Long openTime = response.getOpenTime();
Candlestick updateCandlestick = candlesticksCache.get(openTime);
if (updateCandlestick == null)
{
// new candlestick
updateCandlestick = new Candlestick();
}

// update candlestick with the stream data
...

// Store the updated candlestick in the cache
candlesticksCache.put(openTime, updateCandlestick);

if (openTime > m_LastOpenTime)
{
// need to get the close of the PREVIOUS candle
Candlestick previousCandle = candlesticksCache.get(m_LastOpenTime);
double closingPrice = Double.valueOf(previousCandle.getClose());

EMA_10.update(closingPrice);
EMA_20.update(closingPrice);

System.out.println(StringUtil.replacePlaceholders("Closing price: %1 | EMA(10): %2 - EMA(20): %3", response.getClose(),
DecimalFormat.format(EMA_10.get(), "#.#####"),
DecimalFormat.format(EMA_20.get(), "#.#####")));

m_LastOpenTime = openTime;
}
});

您可能会在第一次响应时遇到异常,因为堆栈中还没有蜡烛,而且我们没有 m_LastOpenTime。您可以在调用 client.onCandlestickEvent() 之前获取当前服务器时间:

private void startCandlestickEventStreaming(String symbol, CandlestickInterval interval)
{
BinanceApiClientFactory factory = BinanceApiClientFactory.newInstance();
BinanceApiWebSocketClient client = factory.newWebSocketClient();

BinanceApiRestClient restClient = factory.newRestClient();
m_LastOpenTime = restClient.getServerTime();

client.onCandlestickEvent(symbol.toLowerCase(), interval, response -> {
...
}
}

关于java - 与币安不同的 EMA(指数移动平均线),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65727498/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com