在本文中,我们将带你了解NumPy版本的“指数加权移动平均线”,等效于pandas.ewm在这篇文章中,我们将为您详细介绍NumPy版本的“指数加权移动平均线”,等效于pandas.ewm的方方面面,
在本文中,我们将带你了解NumPy版本的“指数加权移动平均线”,等效于pandas.ewm在这篇文章中,我们将为您详细介绍NumPy版本的“指数加权移动平均线”,等效于pandas.ewm的方方面面,并解答。mean常见的疑惑,同时我们还将给您一些技巧,以帮助您实现更有效的Arrays.stream()。map()。sum()的不稳定性能、C#- 双指数移动平均线 (DEMA) 到三重指数移动平均线 (TEMA)、Java OutputStream等效于getClass()。getClassLoader()。getResourceAsStream()、Matlab正态分布、历史模拟法、加权移动平均线 EWMA估计风险价值VaR和回测标准普尔指数 S&P500时间序列。
本文目录一览:- NumPy版本的“指数加权移动平均线”,等效于pandas.ewm()。mean()(python 指数加权)
- Arrays.stream()。map()。sum()的不稳定性能
- C#- 双指数移动平均线 (DEMA) 到三重指数移动平均线 (TEMA)
- Java OutputStream等效于getClass()。getClassLoader()。getResourceAsStream()
- Matlab正态分布、历史模拟法、加权移动平均线 EWMA估计风险价值VaR和回测标准普尔指数 S&P500时间序列
NumPy版本的“指数加权移动平均线”,等效于pandas.ewm()。mean()(python 指数加权)
像下面的熊猫一样,如何在NumPy中获得指数加权移动平均值?
import pandas as pdimport pandas_datareader as pdrfrom datetime import datetime# Declare variablesibm = pdr.get_data_yahoo(symbols=''IBM'', start=datetime(2000, 1, 1), end=datetime(2012, 1, 1)).reset_index(drop=True)[''Adj Close'']windowSize = 20# Get PANDAS exponential weighted moving averageewm_pd = pd.DataFrame(ibm).ewm(span=windowSize, min_periods=windowSize).mean().as_matrix()print(ewm_pd)
我用NumPy尝试了以下
import numpy as npimport pandas_datareader as pdrfrom datetime import datetime# From this post: http://stackoverflow.com/a/40085052/3293881 by @Divakardef strided_app(a, L, S): # Window len = L, Stride len/stepsize = S nrows = ((a.size - L) // S) + 1 n = a.strides[0] return np.lib.stride_tricks.as_strided(a, shape=(nrows, L), strides=(S * n, n))def numpyEWMA(price, windowSize): weights = np.exp(np.linspace(-1., 0., windowSize)) weights /= weights.sum() a2D = strided_app(price, windowSize, 1) returnArray = np.empty((price.shape[0])) returnArray.fill(np.nan) for index in (range(a2D.shape[0])): returnArray[index + windowSize-1] = np.convolve(weights, a2D[index])[windowSize - 1:-windowSize + 1] return np.reshape(returnArray, (-1, 1))# Declare variablesibm = pdr.get_data_yahoo(symbols=''IBM'', start=datetime(2000, 1, 1), end=datetime(2012, 1, 1)).reset_index(drop=True)[''Adj Close'']windowSize = 20# Get NumPy exponential weighted moving averageewma_np = numpyEWMA(ibm, windowSize)print(ewma_np)
但是结果却与大熊猫不同。
是否有更好的方法直接在NumPy中计算指数加权移动平均值并获得与完全相同的结果pandas.ewm().mean()
?
在对熊猫解决方案提出60,000个请求时,我得到了大约230秒。我敢肯定,使用纯NumPy可以大大减少这种情况。
答案1
小编典典更新于08/06/2019
大型输入的纯,快速和保护的解决方案
out
用于就地计算的 dtype
参数,参数,索引order
参数
此功能等效于pandas’ewm(adjust=False).mean()
,但速度更快。ewm(adjust=True).mean()
(熊猫的默认设置)可以在结果开始时产生不同的值。我正在努力adjust
为该解决方案添加功能。
当输入太大时,@Divakar的答案会导致浮点精度问题。这是因为,(1-alpha)**(n+1) -> 0
当n ->inf
和时alpha -> 1
,会导致被零除,并且NaN
在计算中会弹出值。
我想我终于破解了!
这是numpy_ewma
功能的向量化版本,据称它可以从@RaduS''s post
-产生正确的结果
def numpy_ewma_vectorized(data, window): alpha = 2 /(window + 1.0) alpha_rev = 1-alpha scale = 1/alpha_rev n = data.shape[0] r = np.arange(n) scale_arr = scale**r offset = data[0]*alpha_rev**(r+1) pw0 = alpha*alpha_rev**(n-1) mult = data*pw0*scale_arr cumsums = mult.cumsum() out = offset + cumsums*scale_arr[::-1] return out
进一步提升
我们可以通过重复使用一些代码来进一步增强它,例如-
def numpy_ewma_vectorized_v2(data, window): alpha = 2 /(window + 1.0) alpha_rev = 1-alpha n = data.shape[0] pows = alpha_rev**(np.arange(n+1)) scale_arr = 1/pows[:-1] offset = data[0]*pows[1:] pw0 = alpha*alpha_rev**(n-1) mult = data*pw0*scale_arr cumsums = mult.cumsum() out = offset + cumsums*scale_arr[::-1] return out
运行时测试
让我们将这两个时间与大型数据集的相同循环函数进行比较。
In [97]: data = np.random.randint(2,9,(5000)) ...: window = 20 ...:In [98]: np.allclose(numpy_ewma(data, window), numpy_ewma_vectorized(data, window))Out[98]: TrueIn [99]: np.allclose(numpy_ewma(data, window), numpy_ewma_vectorized_v2(data, window))Out[99]: TrueIn [100]: %timeit numpy_ewma(data, window)100 loops, best of 3: 6.03 ms per loopIn [101]: %timeit numpy_ewma_vectorized(data, window)1000 loops, best of 3: 665 µs per loopIn [102]: %timeit numpy_ewma_vectorized_v2(data, window)1000 loops, best of 3: 357 µs per loopIn [103]: 6030/357.0Out[103]: 16.89075630252101
加速约17倍!
这是我最快的解决方案,几乎没有向量问题,几乎没有向量化。它有点复杂,但是性能却很好,尤其是对于非常庞大的输入。不使用就地计算(可以使用out
参数来节省内存分配时间):在相当老的PC上,对于100M元素输入向量为3.62秒,对于100K元素输入向量为3.2ms,对于5000个元素输入向量为293µs
(结果会因alpha
/row_size
值而异)。
# tested with python3 & numpy 1.15.2import numpy as npdef ewma_vectorized_safe(data, alpha, row_size=None, dtype=None, order=''C'', out=None): """ Reshapes data before calculating EWMA, then iterates once over the rows to calculate the offset without precision issues :param data: Input data, will be flattened. :param alpha: scalar float in range (0,1) The alpha parameter for the moving average. :param row_size: int, optional The row size to use in the computation. High row sizes need higher precision, low values will impact performance. The optimal value depends on the platform and the alpha being used. Higher alpha values require lower row size. Default depends on dtype. :param dtype: optional Data type used for calculations. Defaults to float64 unless data.dtype is float32, then it will use float32. :param order: {''C'', ''F'', ''A''}, optional Order to use when flattening the data. Defaults to ''C''. :param out: ndarray, or None, optional A location into which the result is stored. If provided, it must have the same shape as the desired output. If not provided or `None`, a freshly-allocated array is returned. :return: The flattened result. """ data = np.array(data, copy=False) if dtype is None: if data.dtype == np.float32: dtype = np.float32 else: dtype = np.float else: dtype = np.dtype(dtype) row_size = int(row_size) if row_size is not None else get_max_row_size(alpha, dtype) if data.size <= row_size: # The normal function can handle this input, use that return ewma_vectorized(data, alpha, dtype=dtype, order=order, out=out) if data.ndim > 1: # flatten input data = np.reshape(data, -1, order=order) if out is None: out = np.empty_like(data, dtype=dtype) else: assert out.shape == data.shape assert out.dtype == dtype row_n = int(data.size // row_size) # the number of rows to use trailing_n = int(data.size % row_size) # the amount of data leftover first_offset = data[0] if trailing_n > 0: # set temporary results to slice view of out parameter out_main_view = np.reshape(out[:-trailing_n], (row_n, row_size)) data_main_view = np.reshape(data[:-trailing_n], (row_n, row_size)) else: out_main_view = out data_main_view = data # get all the scaled cumulative sums with 0 offset ewma_vectorized_2d(data_main_view, alpha, axis=1, offset=0, dtype=dtype, order=''C'', out=out_main_view) scaling_factors = (1 - alpha) ** np.arange(1, row_size + 1) last_scaling_factor = scaling_factors[-1] # create offset array offsets = np.empty(out_main_view.shape[0], dtype=dtype) offsets[0] = first_offset # iteratively calculate offset for each row for i in range(1, out_main_view.shape[0]): offsets[i] = offsets[i - 1] * last_scaling_factor + out_main_view[i - 1, -1] # add the offsets to the result out_main_view += offsets[:, np.newaxis] * scaling_factors[np.newaxis, :] if trailing_n > 0: # process trailing data in the 2nd slice of the out parameter ewma_vectorized(data[-trailing_n:], alpha, offset=out_main_view[-1, -1], dtype=dtype, order=''C'', out=out[-trailing_n:]) return outdef get_max_row_size(alpha, dtype=float): assert 0. <= alpha < 1. # This will return the maximum row size possible on # your platform for the given dtype. I can find no impact on accuracy # at this value on my machine. # Might not be the optimal value for speed, which is hard to predict # due to numpy''s optimizations # Use np.finfo(dtype).eps if you are worried about accuracy # and want to be extra safe. epsilon = np.finfo(dtype).tiny # If this produces an OverflowError, make epsilon larger return int(np.log(epsilon)/np.log(1-alpha)) + 1
一维ewma函数:
def ewma_vectorized(data, alpha, offset=None, dtype=None, order=''C'', out=None): """ Calculates the exponential moving average over a vector. Will fail for large inputs. :param data: Input data :param alpha: scalar float in range (0,1) The alpha parameter for the moving average. :param offset: optional The offset for the moving average, scalar. Defaults to data[0]. :param dtype: optional Data type used for calculations. Defaults to float64 unless data.dtype is float32, then it will use float32. :param order: {''C'', ''F'', ''A''}, optional Order to use when flattening the data. Defaults to ''C''. :param out: ndarray, or None, optional A location into which the result is stored. If provided, it must have the same shape as the input. If not provided or `None`, a freshly-allocated array is returned. """ data = np.array(data, copy=False) if dtype is None: if data.dtype == np.float32: dtype = np.float32 else: dtype = np.float64 else: dtype = np.dtype(dtype) if data.ndim > 1: # flatten input data = data.reshape(-1, order) if out is None: out = np.empty_like(data, dtype=dtype) else: assert out.shape == data.shape assert out.dtype == dtype if data.size < 1: # empty input, return empty array return out if offset is None: offset = data[0] alpha = np.array(alpha, copy=False).astype(dtype, copy=False) # scaling_factors -> 0 as len(data) gets large # this leads to divide-by-zeros below scaling_factors = np.power(1. - alpha, np.arange(data.size + 1, dtype=dtype), dtype=dtype) # create cumulative sum array np.multiply(data, (alpha * scaling_factors[-2]) / scaling_factors[:-1], dtype=dtype, out=out) np.cumsum(out, dtype=dtype, out=out) # cumsums / scaling out /= scaling_factors[-2::-1] if offset != 0: offset = np.array(offset, copy=False).astype(dtype, copy=False) # add offsets out += offset * scaling_factors[1:] return out
2D ewma函数:
def ewma_vectorized_2d(data, alpha, axis=None, offset=None, dtype=None, order=''C'', out=None): """ Calculates the exponential moving average over a given axis. :param data: Input data, must be 1D or 2D array. :param alpha: scalar float in range (0,1) The alpha parameter for the moving average. :param axis: The axis to apply the moving average on. If axis==None, the data is flattened. :param offset: optional The offset for the moving average. Must be scalar or a vector with one element for each row of data. If set to None, defaults to the first value of each row. :param dtype: optional Data type used for calculations. Defaults to float64 unless data.dtype is float32, then it will use float32. :param order: {''C'', ''F'', ''A''}, optional Order to use when flattening the data. Ignored if axis is not None. :param out: ndarray, or None, optional A location into which the result is stored. If provided, it must have the same shape as the desired output. If not provided or `None`, a freshly-allocated array is returned. """ data = np.array(data, copy=False) assert data.ndim <= 2 if dtype is None: if data.dtype == np.float32: dtype = np.float32 else: dtype = np.float64 else: dtype = np.dtype(dtype) if out is None: out = np.empty_like(data, dtype=dtype) else: assert out.shape == data.shape assert out.dtype == dtype if data.size < 1: # empty input, return empty array return out if axis is None or data.ndim < 2: # use 1D version if isinstance(offset, np.ndarray): offset = offset[0] return ewma_vectorized(data, alpha, offset, dtype=dtype, order=order, out=out) assert -data.ndim <= axis < data.ndim # create reshaped data views out_view = out if axis < 0: axis = data.ndim - int(axis) if axis == 0: # transpose data views so columns are treated as rows data = data.T out_view = out_view.T if offset is None: # use the first element of each row as the offset offset = np.copy(data[:, 0]) elif np.size(offset) == 1: offset = np.reshape(offset, (1,)) alpha = np.array(alpha, copy=False).astype(dtype, copy=False) # calculate the moving average row_size = data.shape[1] row_n = data.shape[0] scaling_factors = np.power(1. - alpha, np.arange(row_size + 1, dtype=dtype), dtype=dtype) # create a scaled cumulative sum array np.multiply( data, np.multiply(alpha * scaling_factors[-2], np.ones((row_n, 1), dtype=dtype), dtype=dtype) / scaling_factors[np.newaxis, :-1], dtype=dtype, out=out_view ) np.cumsum(out_view, axis=1, dtype=dtype, out=out_view) out_view /= scaling_factors[np.newaxis, -2::-1] if not (np.size(offset) == 1 and offset == 0): offset = offset.astype(dtype, copy=False) # add the offsets to the scaled cumulative sums out_view += offset[:, np.newaxis] * scaling_factors[np.newaxis, 1:] return out
用法:
data_n = 100000000data = ((0.5*np.random.randn(data_n)+0.5) % 1) * 100span = 5000 # span >= 1alpha = 2/(span+1) # for pandas` span parameter# com = 1000 # com >= 0# alpha = 1/(1+com) # for pandas` center-of-mass parameter# halflife = 100 # halflife > 0# alpha = 1 - np.exp(np.log(0.5)/halflife) # for pandas` half-life parameterresult = ewma_vectorized_safe(data, alpha)
只是一个提示
根据给定alpha
窗口中数据对平均值的贡献,很容易为给定的计算“窗口大小”(技术指数平均值具有无限的“窗口”)。例如,这对于选择由于边界效应而将结果的起始部分视为不可靠的情况很有用。
def window_size(alpha, sum_proportion): # Increases with increased sum_proportion and decreased alpha # solve (1-alpha)**window_size = (1-sum_proportion) for window_size return int(np.log(1-sum_proportion) / np.log(1-alpha))alpha = 0.02sum_proportion = .99 # window covers 99% of contribution to the moving averagewindow = window_size(alpha, sum_proportion) # = 227sum_proportion = .75 # window covers 75% of contribution to the moving averagewindow = window_size(alpha, sum_proportion) # = 68
alpha = 2 / (window_size +1.0)
此线程中使用的关系(pandas的’span’选项)与上述函数(带有sum_proportion~=0.87
)的逆函数非常近似。alpha = 1 -np.exp(np.log(1-sum_proportion)/window_size)
更准确(pandas的“半衰期”选项等于sum_proportion=0.5
)。
在下面的示例中,data
代表一个连续的噪声信号。cutoff_idx
是第一个位置,result
其中至少99%的值取决于其中的单独值data
(即小于1%的值取决于data
[0])。直到cutoff_idx
最终的数据都被排除在数据之外,因为它太依赖于中的第一个值data
,因此可能会扭曲平均值。
result = ewma_vectorized_safe(data, alpha, chunk_size)sum_proportion = .99cutoff_idx = window_size(alpha, sum_proportion)result = result[cutoff_idx:]
为了说明上面解决的问题,您可以运行几次,请注意,红线经常出现的错误的开始,在以下位置被跳过cutoff_idx
:
data_n = 100000data = np.random.rand(data_n) * 100window = 1000sum_proportion = .99alpha = 1 - np.exp(np.log(1-sum_proportion)/window)result = ewma_vectorized_safe(data, alpha)cutoff_idx = window_size(alpha, sum_proportion)x = np.arange(start=0, stop=result.size)import matplotlib.pyplot as pltplt.plot(x[:cutoff_idx+1], result[:cutoff_idx+1], ''-r'', x[cutoff_idx:], result[cutoff_idx:], ''-b'')plt.show()
请注意,cutoff_idx==window
因为alpha是用window_size()
函数的反函数设置的,所以具有sum_proportion
。这类似于大熊猫的用法ewm(span=window,min_periods=window)
。
Arrays.stream()。map()。sum()的不稳定性能
我遇到了一个非常原始的数组上非常简单的map / reduce操作的性能配置文件实例。这是我的jmh基准代码:
@OutputTimeUnit(TimeUnit.NANOSECONDS)@BenchmarkMode(Mode.AverageTime)@OperationsPerInvocation(Measure.ARRAY_SIZE)@Warmup(iterations = 300, time = 200, timeUnit=MILLISECONDS)@Measurement(iterations = 1, time = 1000, timeUnit=MILLISECONDS)@State(Scope.Thread)@Threads(1)@Fork(1)public class Measure{ static final int ARRAY_SIZE = 1<<20; final int[] ds = new int[ARRAY_SIZE]; private IntUnaryOperator mapper; @Setup public void setup() { setAll(ds, i->(int)(Math.random()*(1<<7))); final int multiplier = (int)(Math.random()*10); mapper = d -> multiplier*d; } @Benchmark public double multiply() { return Arrays.stream(ds).map(mapper).sum(); }}
以下是典型输出的摘要:
# VM invoker: /Library/Java/JavaVirtualMachines/jdk1.8.0_20.jdk/Contents/Home/jre/bin/java# VM options: <none># Warmup: 300 iterations, 200 ms each# Measurement: 1 iterations, 1000 ms each# Threads: 1 thread, will synchronize iterations# Benchmark mode: Average time, time/op# Benchmark: org.sample.Measure.multiply# Run progress: 0,00% complete, ETA 00:01:01# Fork: 1 of 1# Warmup Iteration 1: 0,779 ns/op# Warmup Iteration 2: 0,684 ns/op# Warmup Iteration 3: 0,608 ns/op# Warmup Iteration 4: 0,619 ns/op# Warmup Iteration 5: 0,642 ns/op# Warmup Iteration 6: 0,638 ns/op# Warmup Iteration 7: 0,660 ns/op# Warmup Iteration 8: 0,611 ns/op# Warmup Iteration 9: 0,636 ns/op# Warmup Iteration 10: 0,692 ns/op# Warmup Iteration 11: 0,632 ns/op# Warmup Iteration 12: 0,612 ns/op# Warmup Iteration 13: 1,280 ns/op# Warmup Iteration 14: 7,261 ns/op# Warmup Iteration 15: 7,379 ns/op# Warmup Iteration 16: 7,376 ns/op# Warmup Iteration 17: 7,379 ns/op# Warmup Iteration 18: 7,195 ns/op# Warmup Iteration 19: 7,351 ns/op# Warmup Iteration 20: 7,761 ns/op............# Warmup Iteration 100: 7,300 ns/op# Warmup Iteration 101: 7,384 ns/op# Warmup Iteration 102: 7,132 ns/op# Warmup Iteration 103: 7,278 ns/op# Warmup Iteration 104: 7,331 ns/op# Warmup Iteration 105: 7,335 ns/op# Warmup Iteration 106: 7,450 ns/op# Warmup Iteration 107: 7,346 ns/op# Warmup Iteration 108: 7,826 ns/op# Warmup Iteration 109: 7,221 ns/op# Warmup Iteration 110: 8,017 ns/op# Warmup Iteration 111: 7,611 ns/op# Warmup Iteration 112: 7,376 ns/op# Warmup Iteration 113: 0,707 ns/op# Warmup Iteration 114: 0,828 ns/op# Warmup Iteration 115: 0,608 ns/op# Warmup Iteration 116: 0,634 ns/op# Warmup Iteration 117: 0,633 ns/op# Warmup Iteration 118: 0,660 ns/op# Warmup Iteration 119: 0,635 ns/op# Warmup Iteration 120: 0,566 ns/op
关键时刻发生在迭代13和113:首先将性能降低十倍,然后将其恢复。相应的时间是测试运行的2.5和22.5秒。这些事件的时间对阵列大小BTW非常敏感。
有什么可能解释这种行为?JIT编译器可能已经在第一次迭代中完成了工作。没有要说的GC操作(由VisualVM确认)…对于任何种类的解释,我都完全不知所措。
我的Java版本(OS X):
$ java -versionjava version "1.8.0_20"Java(TM) SE Runtime Environment (build 1.8.0_20-b26)Java HotSpot(TM) 64-Bit Server VM (build 25.20-b23, mixed mode)
答案1
小编典典JIT将首先编译热循环,该热循环将迭代并操作(映射/减少)数组元素。由于数组包含2个20个元素,因此发生的时间很早。
稍后,JIT编译管道,最有可能在已编译的基准测试方法中内联,并且由于内联限制而无法将其全部编译为一种方法。恰好发生在热循环中达到那些内联限制的情况,并且没有内联对map或sum的调用,因此热循环被无意间“取消了优化”。
-XX:+UnlockDiagnosticVMOptions -XX:+PrintCompilation-XX:+PrintInlining
运行基准测试时使用这些选项,尽早看到以下输出:
1202 487 % 4 java.util.Spliterators$IntArraySpliterator::forEachRemaining @ 49 (68 bytes) @ 53 java.util.stream.IntPipeline$3$1::accept (23 bytes) inline (hot) \-> TypeProfile (1186714/1186714 counts) = java/util/stream/IntPipeline$3$1 @ 12 test.Measure$$Lambda$2/1745776415::applyAsInt (9 bytes) inline (hot) \-> TypeProfile (1048107/1048107 counts) = test/Measure$$Lambda$2 @ 5 test.Measure::lambda$setup$1 (4 bytes) inline (hot) @ 17 java.util.stream.ReduceOps$5ReducingSink::accept (19 bytes) inline (hot) \-> TypeProfile (1048107/1048107 counts) = java/util/stream/ReduceOps$5ReducingSink @ 10 java.util.stream.IntPipeline$$Lambda$3/1779653790::applyAsInt (6 bytes) inline (hot) \-> TypeProfile (1048064/1048064 counts) = java/util/stream/IntPipeline$$Lambda$3 @ 2 java.lang.Integer::sum (4 bytes) inline (hot)
那就是编译的热循环。(这%
意味着已替换堆栈或OSR)
稍后再进行流管道的编译(我怀疑基准方法有10,000次迭代,但我尚未验证):
@ 16 java.util.stream.IntPipeline::sum (11 bytes) inline (hot) \-> TypeProfile (5120/5120 counts) = java/util/stream/IntPipeline$3 @ 2 java.lang.invoke.LambdaForm$MH/1279902262::linkToTargetMethod (8 bytes) force inline by annotation @ 4 java.lang.invoke.LambdaForm$MH/1847865997::identity (18 bytes) force inline by annotation @ 14 java.lang.invoke.LambdaForm$DMH/2024969684::invokeStatic_L_L (14 bytes) force inline by annotation @ 1 java.lang.invoke.DirectMethodHandle::internalMemberName (8 bytes) force inline by annotation @ 10 sun.invoke.util.ValueConversions::identity (2 bytes) inline (hot) @ 7 java.util.stream.IntPipeline::reduce (16 bytes) inline (hot) @ 3 java.util.stream.ReduceOps::makeInt (18 bytes) inline (hot) @ 1 java.util.Objects::requireNonNull (14 bytes) inline (hot) @ 14 java.util.stream.ReduceOps$5::<init> (16 bytes) inline (hot) @ 12 java.util.stream.ReduceOps$ReduceOp::<init> (10 bytes) inline (hot) @ 1 java.lang.Object::<init> (1 bytes) inline (hot) @ 6 java.util.stream.AbstractPipeline::evaluate (94 bytes) inline (hot) @ 50 java.util.stream.AbstractPipeline::isParallel (8 bytes) inline (hot) @ 80 java.util.stream.TerminalOp::getOpFlags (2 bytes) inline (hot) \-> TypeProfile (5122/5122 counts) = java/util/stream/ReduceOps$5 @ 85 java.util.stream.AbstractPipeline::sourceSpliterator (163 bytes) inline (hot) @ 79 java.util.stream.AbstractPipeline::isParallel (8 bytes) inline (hot) @ 88 java.util.stream.ReduceOps$ReduceOp::evaluateSequential (18 bytes) inline (hot) @ 2 java.util.stream.ReduceOps$5::makeSink (5 bytes) inline (hot) @ 1 java.util.stream.ReduceOps$5::makeSink (16 bytes) inline (hot) @ 12 java.util.stream.ReduceOps$5ReducingSink::<init> (15 bytes) inline (hot) @ 11 java.lang.Object::<init> (1 bytes) inline (hot) @ 6 java.util.stream.AbstractPipeline::wrapAndCopyInto (18 bytes) inline (hot) @ 3 java.util.Objects::requireNonNull (14 bytes) inline (hot) @ 9 java.util.stream.AbstractPipeline::wrapSink (37 bytes) inline (hot) @ 1 java.util.Objects::requireNonNull (14 bytes) inline (hot) @ 23 java.util.stream.IntPipeline$3::opWrapSink (10 bytes) inline (hot) \-> TypeProfile (4868/4868 counts) = java/util/stream/IntPipeline$3 @ 6 java.util.stream.IntPipeline$3$1::<init> (11 bytes) inline (hot) @ 7 java.util.stream.Sink$ChainedInt::<init> (16 bytes) inline (hot) @ 1 java.lang.Object::<init> (1 bytes) inline (hot) @ 6 java.util.Objects::requireNonNull (14 bytes) inline (hot) @ 13 java.util.stream.AbstractPipeline::copyInto (53 bytes) inline (hot) @ 1 java.util.Objects::requireNonNull (14 bytes) inline (hot) @ 9 java.util.stream.AbstractPipeline::getStreamAndOpFlags (5 bytes) accessor @ 12 java.util.stream.StreamOpFlag::isKnown (19 bytes) inline (hot) @ 20 java.util.Spliterator::getExactSizeIfKnown (25 bytes) inline (hot) \-> TypeProfile (4870/4870 counts) = java/util/Spliterators$IntArraySpliterator @ 1 java.util.Spliterators$IntArraySpliterator::characteristics (5 bytes) accessor @ 19 java.util.Spliterators$IntArraySpliterator::estimateSize (11 bytes) inline (hot) @ 25 java.util.stream.Sink$ChainedInt::begin (11 bytes) inline (hot) \-> TypeProfile (4870/4870 counts) = java/util/stream/IntPipeline$3$1 @ 5 java.util.stream.ReduceOps$5ReducingSink::begin (9 bytes) inline (hot) \-> TypeProfile (4871/4871 counts) = java/util/stream/ReduceOps$5ReducingSink @ 32 java.util.Spliterator$OfInt::forEachRemaining (53 bytes) inline (hot) @ 12 java.util.Spliterators$IntArraySpliterator::forEachRemaining (68 bytes) inline (hot) @ 53 java.util.stream.IntPipeline$3$1::accept (23 bytes) inline (hot) @ 12 test.Measure$$Lambda$2/1745776415::applyAsInt (9 bytes) inline (hot) \-> TypeProfile (1048107/1048107 counts) = test/Measure$$Lambda$2 @ 5 test.Measure::lambda$setup$1 (4 bytes) inlining too deep @ 17 java.util.stream.ReduceOps$5ReducingSink::accept (19 bytes) inline (hot) \-> TypeProfile (1048107/1048107 counts) = java/util/stream/ReduceOps$5ReducingSink @ 10 java.util.stream.IntPipeline$$Lambda$3/1779653790::applyAsInt (6 bytes) inlining too deep \-> TypeProfile (1048064/1048064 counts) = java/util/stream/IntPipeline$$Lambda$3 @ 53 java.util.stream.IntPipeline$3$1::accept (23 bytes) inline (hot) @ 12 test.Measure$$Lambda$2/1745776415::applyAsInt (9 bytes) inline (hot) \-> TypeProfile (1048107/1048107 counts) = test/Measure$$Lambda$2 @ 5 test.Measure::lambda$setup$1 (4 bytes) inlining too deep @ 17 java.util.stream.ReduceOps$5ReducingSink::accept (19 bytes) inline (hot) \-> TypeProfile (1048107/1048107 counts) = java/util/stream/ReduceOps$5ReducingSink @ 10 java.util.stream.IntPipeline$$Lambda$3/1779653790::applyAsInt (6 bytes) inlining too deep \-> TypeProfile (1048064/1048064 counts) = java/util/stream/IntPipeline$$Lambda$3 @ 38 java.util.stream.Sink$ChainedInt::end (10 bytes) inline (hot) @ 4 java.util.stream.Sink::end (1 bytes) inline (hot) \-> TypeProfile (5120/5120 counts) = java/util/stream/ReduceOps$5ReducingSink @ 12 java.util.stream.ReduceOps$5ReducingSink::get (5 bytes) inline (hot) @ 1 java.util.stream.ReduceOps$5ReducingSink::get (8 bytes) inline (hot) @ 4 java.lang.Integer::valueOf (32 bytes) inline (hot) @ 28 java.lang.Integer::<init> (10 bytes) inline (hot) @ 1 java.lang.Number::<init> (5 bytes) inline (hot) @ 1 java.lang.Object::<init> (1 bytes) inline (hot) @ 12 java.lang.Integer::intValue (5 bytes) accessor
请注意热循环中的方法发生的“内联太深”。
甚至在以后生成的JMH测量循环上进行编译:
26857 685 3 test.generated.Measure_multiply::multiply_avgt_jmhLoop (55 bytes) @ 7 java.lang.System::nanoTime (0 bytes) intrinsic @ 16 test.Measure::multiply (23 bytes) @ 4 java.util.Arrays::stream (8 bytes) @ 4 java.util.Arrays::stream (11 bytes) @ 3 java.util.Arrays::spliterator (10 bytes) @ 6 java.util.Spliterators::spliterator (25 bytes) callee is too large @ 7 java.util.stream.StreamSupport::intStream (14 bytes) @ 6 java.util.stream.StreamOpFlag::fromCharacteristics (37 bytes) callee is too large @ 10 java.util.stream.IntPipeline$Head::<init> (8 bytes) @ 4 java.util.stream.IntPipeline::<init> (8 bytes) @ 4 java.util.stream.AbstractPipeline::<init> (55 bytes) callee is too large @ 11 java.util.stream.IntPipeline::map (26 bytes) @ 1 java.util.Objects::requireNonNull (14 bytes) @ 8 java.lang.NullPointerException::<init> (5 bytes) don''t inline Throwable constructors @ 22 java.util.stream.IntPipeline$3::<init> (20 bytes) @ 16 java.util.stream.IntPipeline$StatelessOp::<init> (29 bytes) callee is too large @ 16 java.util.stream.IntPipeline::sum (11 bytes) @ 2 java.lang.invoke.LambdaForm$MH/1279902262::linkToTargetMethod (8 bytes) force inline by annotation @ 4 java.lang.invoke.LambdaForm$MH/1847865997::identity (18 bytes) force inline by annotation @ 14 java.lang.invoke.LambdaForm$DMH/2024969684::invokeStatic_L_L (14 bytes) force inline by annotation @ 1 java.lang.invoke.DirectMethodHandle::internalMemberName (8 bytes) force inline by annotation @ 10 sun.invoke.util.ValueConversions::identity (2 bytes) @ 7 java.util.stream.IntPipeline::reduce (16 bytes) @ 3 java.util.stream.ReduceOps::makeInt (18 bytes) @ 1 java.util.Objects::requireNonNull (14 bytes) @ 14 java.util.stream.ReduceOps$5::<init> (16 bytes) @ 12 java.util.stream.ReduceOps$ReduceOp::<init> (10 bytes) @ 1 java.lang.Object::<init> (1 bytes) @ 6 java.util.stream.AbstractPipeline::evaluate (94 bytes) callee is too large @ 12 java.lang.Integer::intValue (5 bytes)
请注意,没有尝试内联整个流管道,它在到达热循环之前就已停止运行,请参阅“被调用方太大”,从而重新优化热循环。
例如,可以增加内联限制来避免这种行为-XX:MaxInlineLevel=12
。
C#- 双指数移动平均线 (DEMA) 到三重指数移动平均线 (TEMA)
如何解决C#- 双指数移动平均线 (DEMA) 到三重指数移动平均线 (TEMA)?
请大家帮忙将以下 DEMA 代码转换为 TEMA: 以下是来自币安 API 的数据:
数据:https://fapi.binance.com/fapi/v1/klines?symbol=BTCUSDT&interval=1m
在这个 URL 上,我们有 TEAM 的公式:https://www.investopedia.com/terms/t/triple-exponential-moving-average.asp
using System.Collections.Generic
using System.Linq;
namespace Indicator
{
/// <summary>
/// Double Exponential Moving Average (DEMA)
/// </summary>
public class DEMA : IndicatorCalculatorBase<SingleDoubleSerie>
{
protected override List<Ohlc> OhlcList { get; set; }
protected int Period { get; set; }
protected ColumnType ColumnType { get; set; } = ColumnType.Close;
public DEMA(int period,ColumnType columnType = ColumnType.Close)
{
this.Period = period;
this.ColumnType = columnType;
}
/// <summary>
/// DEMA = 2 * EMA - EMA of EMA
/// </summary>
/// <see cref="http://forex-indicators.net/trend-indicators/dema"/>
/// <returns></returns>
public override SingleDoubleSerie Calculate()
{
SingleDoubleSerie demaSerie = new SingleDoubleSerie();
EMA ema = new EMA(Period,false,ColumnType);
ema.Load(OhlcList);
List<double?> emaValues = ema.Calculate().Values;
// assign EMA values to column
for (int i = 0; i < OhlcList.Count; i++)
{
switch (ColumnType)
{
case ColumnType.Close:
OhlcList[i].Close = emaValues[i] ?? 0.0;
break;
default:
break;
}
}
ema.Load(OhlcList.Skip(Period - 1).ToList());
// EMA(EMA(value))
List<double?> emaEmaValues = ema.Calculate().Values;
for (int i = 0; i < Period - 1; i++)
{
emaEmaValues.Insert(0,null);
}
// Calculate DEMA
for (int i = 0; i < OhlcList.Count; i++)
{
if (i >= 2 * Period - 2)
{
var dema = 2 * emaValues[i] - emaEmaValues[i];
demaSerie.Values.Add(dema);
}
else
{
demaSerie.Values.Add(null);
}
}
return demaSerie;
}
}
}
谢谢
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)
Java OutputStream等效于getClass()。getClassLoader()。getResourceAsStream()
我正在尝试存储对应用程序属性所做的更改。该.properties
文件位于resources
包中,与包含我的UI和模型的包不同。
我使用以下方法打开了包装:
this.getClass().getClassLoader().getResourceAsStream("resources/settings.properties")
是否有与之等效的功能,允许我将对Properties类的更改持久保存在同一.Properties文件中?
答案1
小编典典听起来您想存储用户首选项。考虑为此使用Java Preferences
API。
Matlab正态分布、历史模拟法、加权移动平均线 EWMA估计风险价值VaR和回测标准普尔指数 S&P500时间序列
原文链接:http://tecdat.cn/?p=24480
此示例说明如何使用三种方法估计风险价值 (VaR) 并执行 VaR 回测分析。这三种方法是:
- 正态分布
- 历史模拟
- 指数加权移动平均线 (EWMA)
风险价值是一种量化与投资组合相关的风险水平的统计方法。VaR 衡量指定时间范围内和给定置信水平的最大损失量。
回测衡量 VaR 计算的准确性。使用 VaR 方法,计算损失预测,然后与第二天结束时的实际损失进行比较。预测损失和实际损失之间的差异程度表明 VaR 模型是低估还是高估了风险。因此,回测回顾数据并有助于评估 VaR 模型。
本示例中使用的三种估计方法在 95% 和 99% 的置信水平下估计 VaR。
加载数据并定义测试窗口
加载数据。本例中使用的数据来自标准普尔指数从 1993 年到 2003 年的时间序列收益率。
tik2rt(sp);
将估计窗口定义为 250 个交易日。测试窗口从 1996 年的第一天开始,一直持续到样本结束。
WinSze = 250;
对于 95% 和 99% 的 VaR 置信水平。
p = \[0.05 0.01\];
这些值意味着分别有至多 5% 和 1% 的概率发生的损失将大于最大阈值(即大于 VaR)。
使用正态分布方法计算 VaR
对于正态分布法,假设投资组合的损益呈正态分布。使用此假设,通过将每个置信水平的_z_分数乘以收益率的标准差来计算 VaR 。由于 VaR 回溯测试对数据进行追溯,因此“今天”的 VaR 是根据过去_N_ = 250 天(但不包括“今天”)的收益率值计算得出的 。
for t = TtWnow
i = t - TsWidoSrt + 1;
Esationdw = t-EtiWinwSze:t-1;
gma = std(Returns(tmWinow));
Noa95(i) = -Zscre(1)*Sima;
Nrml99(i) = -Zsore(2)*Sigma;
end
plot(DaeRtuns(TsWidw),\[Nrm95 oma99\])
正态分布方法也称为参数 VaR,因为它的估计涉及计算收益率标准差的参数。正态分布方法的优点是简单。然而,正态分布方法的弱点是假设收益率是正态分布的。正态分布方法的另一个名称是方差-协方差方法。
使用历史模拟方法计算 VaR
与正态分布方法不同,历史模拟 (HS) 是一种非参数方法。它不假设资产收益的特定分布。历史模拟通过假设过去的损益可以作为下一个收益期的损益分配来预测风险。“今天”的 VaR 计算为“今天” 之前 最后_N 次_收益率的 _第 p_个分位数 。
for t = Tstidow
i = t - Tsidwtt + 1;
Htrl95(i) = -qate(X,pVR(1));
Hii99(i) = -qatie(X,pVaR(2));
fiure;
plot(Dtr(Ttow),\[Hic95 Hstrl99\])
从上图可以看出,历史模拟曲线具有分段不变的轮廓。其原因是,在极端事件发生之前,量值在几天内不会发生变化。因此,历史模拟方法对波动率的变化反应缓慢。
使用指数加权移动平均法 (EWMA) 计算 VaR
前两个 VaR 方法假设所有过去的收益率都具有相同的权重。指数加权移动平均 (EWMA) 方法分配不相等的权重,尤其是指数递减的权重。最近的收益率具有更高的权重,因为它们对“今天”收益率的影响比过去更远的收益率更大。大小估计窗口上的 EWMA 方差公式 是:
是归一化常数:
为方便起见,我们假设一个无限大的估计窗口来近似方差:
实践中经常使用的衰减因子的值为0.94。这是本示例中使用的值。
启动 EWMA 设置标准偏差。
Laa = 0.94;
for i = 2 : (Tsart-1)
Sm2(i) = (1-Labda) * Rts(i-1)^2 + Lama * m2(i-1);
在测试窗口中使用 EWMA 来估计 VaR。
for t = TeWio
EWMA95 (k) = -Zscre(1)*Sima;
EWMA99(k) = -Zsoe(2)*Siga;
end
plot(DR,\[EWMA95 EWMA99\])
在上图中,EWMA 对大(或小)收益率时期的反应非常迅速。
VaR回测
在本示例的第一部分中,使用三种不同的方法和两种不同的 VaR 置信水平在测试窗口上估计了 VaR。VaR 回测的目标是评估 VaR 模型的性能。95% 置信度的 VaR 估计值仅在大约 5% 的时间内被违反。VaR 失败的集群表明缺乏跨时间的独立性,因为 VaR 模型对不断变化的市场条件反应缓慢。
VaR 回测分析中常见的第一步是将收益率和 VaR 估计值绘制在一起。在 95% 的置信水平上绘制所有三种方法,并将它们与收益率进行比较。
Rtnet = Rrns(Tstnow);
DesTst = Das(TsWnow);
fige;
plot
为了突出不同的方法如何对不断变化的市场条件做出不同的反应,您可以放大收益率值发生巨大和突然变化的时间序列。例如,大约在 1998 年 8 月:
Zm = (Da >= da(1998,8,5)) & (D <= da(1998,10,31);
br(D,);
for i = 1 : sze(Vata,2)
sts(D-0.5,VaRData(:,i),VaFt{i});
plot(D(IN95),-N(nN95)
当收益为负 VaR 时,就会发生 VaR 失败。仔细观察 8 月 27 日至 8 月 31 日,会发现收益率显着下降。从 8 月 27 日起,EWMA 更密切、更准确地跟踪收益率趋势。因此,与正态分布方法(7次失败,蓝色)或历史模拟方法(8次失败,红色)相比,EWMA 的 VaR 失败(2)次失败,紫色)较少。
除了可视化工具,您还可以使用统计测试进行 VaR 回测。在此示例中,首先比较正态分布方法在 95% 和 99% VaR 水平下的不同测试结果。
bctet(etet,\[Nrml95 Noml99\]);
summary
摘要报告显示观察到的水平与定义的 VaR 水平足够接近。95% 和 99% VaR 水平至多具有期望失败,其中 _N_ 是观察次数。失败率表明 VaR 水平在范围内,而 VaR 水平不精确并且低估了风险。运行所有支持的测试 (1-VaR_level) x _N_
test(vt)
95%的VaR通过了测试,如二项式和失败比例测试(TL、BIN和POF列)。99%的VaR没有通过这些相同的测试,如拒绝结果所示。在条件覆盖率独立性和间隔时间独立性(ci和tbfi列)中,两个置信度都被拒绝。这个结果表明,VaR的违反不是独立的,可能在短时间内有多次失败的时期。另外,一次失败可能会使其他失败在随后的日子里更有可能发生。
在两个 VaR 置信水平下对三种方法的投资组合运行相同的测试。
rbackest
结果和之前的结果差不多,在95%的水平上,结果基本可以接受。然而,在 99% 水平的结果通常是拒绝。关于独立性,大多数测试通过了条件覆盖独立性测试,连续几天测试独立性。请注意,所有测试都失败了独立性测试之间的时间间隔,它考虑了所有失败之间的时间。这个结果表明所有方法都存在独立性假设的问题。
为了更好地了解这些结果如何在市场条件下发生变化,请查看 2000 年和 2002 年的 95% VaR 置信水平。
n00 = yar(aet) == 2000);
I22 = (ea) == 2002);
v202 = rbks(RtrTt(n202
2000年,这三种方法都通过了所有的测试。但是,2002 年的测试结果大多是所有方法都被拒绝。EWMA 方法似乎在 2002 年表现更好,但所有方法都未能通过独立性测试。
要更深入地了解独立性测试,请查看条件覆盖独立性和失败间隔时间独立性2002 年的测试详细信息。运行各个测试功能。
cci
在 CCI 测试中,知道在时间_t_ -1没有失败的情况下, 在时间_t_发生失败 的概率 _p_ 由下式给出01
在时间_t_发生失败 的概率 _p_ ,知道在时间_t_ -1发生失败, 由下式给出11
从 测试结果中的N00
, N10
, N01
, N11
列来看 , 三种方法的_p_ 值 01
都在 5% 左右,而_p_ 值 11
都在 20% 以上。因为有证据表明一个失败之后出现另一个失败的频率远高于 5%,所以这个 CCI 测试失败了。
在失败间隔时间独立性测试中,查看失败间隔时间分布的最小值、最大值和四分位数,在TBFMin
、 TBFQ1
、 TBFQ2
、 TBFQ3
、 列中 TBFMax
。
tbfi
对于 95% 的 VaR 水平,您预计失败之间的平均时间为 20 天,或每 20 天发生一次失败。但是,对于这三种方法,2002 年的失败间隔时间的中位数介于 5 到 7.5 之间。该结果表明,在一半的情况下,连续两次失败发生在 5 到 7 天内,比期望的 20 天要频繁得多。因此,会发生更多的测试失败。对于正态方法,第一个四分位数是 1,这意味着 25% 的失败发生在连续几天。
参考
Danielsson, J. _金融风险预测:预测市场风险的理论和实践_。威利财经,2012 年。
最受欢迎的见解
1.R语言基于ARMA-GARCH-VaR模型拟合和预测实证研究
2.R语言时变参数VAR随机模型
3.R语言估计时变VAR模型时间序列的实证研究
4.R语言基于ARMA-GARCH过程的VAR拟合和预测
5.GARCH(1,1),MA以及历史模拟法的VaR比较
6.R语言用向量自回归(VAR)进行经济数据脉冲响应
7.R语言实现向量自动回归VAR模型
8.R语言随机搜索变量选择SSVS估计贝叶斯向量自回归(BVAR)模型
9.R语言VAR模型的不同类型的脉冲响应分析
今天关于NumPy版本的“指数加权移动平均线”,等效于pandas.ewm和。mean的讲解已经结束,谢谢您的阅读,如果想了解更多关于Arrays.stream()。map()。sum()的不稳定性能、C#- 双指数移动平均线 (DEMA) 到三重指数移动平均线 (TEMA)、Java OutputStream等效于getClass()。getClassLoader()。getResourceAsStream()、Matlab正态分布、历史模拟法、加权移动平均线 EWMA估计风险价值VaR和回测标准普尔指数 S&P500时间序列的相关知识,请在本站搜索。
本文标签: