I am trying to add indicator code, which works perfectly on its own, to an EA MQL4 source. While everything compiles just fine, the terminal tab shows the above error.
Both errors occuring relate to tick[i+k].
double ticks[];
double tick[];
int init() {
ArrayResize(ticks,TotalBars); ArraySetAsSeries(ticks,true);
ArrayResize(tick,TotalBars); ArraySetAsSeries(tick,true);
return(0);
}
int start() {
for (i=TotalBars-1; i>=0; i--)
{
avg = tick[i];
for (k=1; k<AveragePeriod && tick[i+k]!=0; k++) avg += tick[i+k];
avg /= k;
....
I want to prevent iCustom calls. What could be the issue?
Thank you.
Related
I have a kernel Metal function which basically looks like this:
struct Matrix {
half arr[562500]; //enough to store 750x750 matrix
};
struct Output {
half arr[12288];
};
kernel void compute_features(device Output& buffer [[ buffer(0) ]],
const device Matrix& mtx_0 [[ buffer(1) ]],
const device Matrix& mtx_1 [[ buffer(2) ]],
constant short2& matSize [[ buffer(3) ]],
constant float& offset [[ buffer(4) ]],
ushort2 gid [[ thread_position_in_grid ]]) {
for (int i = 0; i < 12; i++) {
for (int j = 0; j < 12; j++) {
int mat_id = i * matSize.x + j;
half matrixValue_0 = mtx_0.mat[mat_id];
half matrixValue_1 = mtx_1.mat[mat_id] - offset;
short someId_0 = 0;
short someId_1 = 0;
short someId_2 = 0;
short someId_3 = 0; //those ids will be calculated at the code below
half value = 0.h; //this value will be calculated at the code below
//some math where `someId` and `value` are calculated with usage of `matrixValue_0` and `matrixValue_1`
if (some_condition0) {
buffer.arr[someId_0] += value;
}
if (some_condition1) {
buffer.arr[someId_1] += value;
}
if (some_condition2) {
buffer.arr[someId_2] += value;
}
if (some_condition3) {
buffer.arr[someId_3] += value;
}
}
}
I understand that this code has its down-sides - dynamic indexing and big loop. But unfortunately the algorithm I'm trying to express can not be implemented differently at that point.
Now, this code runs very good at iPhone 7+, it takes around 200 us per iteration, and I'm very happy with this number.
BUT, I tried to run the exact same algorithm on iPhone XR and I was surprised to see that this algorithm takes around 1.0-1.2 ms to complete.
With the help of XCode and it's magnificent GPU pipeline debugging tool I found out that my bottlenecks are:
1)
half matrixValue_0 = mtx_0.mat[mat_id];
half matrixValue_1 = mtx_1.mat[mat_id] - offset;
It seems that significant part of processing time are spent in Memory Load operation.
2)
if (some_condition0) {
buffer[someId_0] += value;
}
if (some_condition1) {
buffer[someId_1] += value;
}
if (some_condition2) {
buffer[someId_2] += value;
}
if (some_condition3) {
buffer[someId_3] += value;
}
The major processing time are spent for Memory Store operation.
For me it seems like iPhone XR quite struggles operating with device memory because bottle-necks are in places where I work with containers from device memory.
I understand that I'm using dynamic indexing - compiler can not really predict what address in the container will be loaded/stored in certain iteration. But the code works very good on iPhone 7+, but not on iPhone XR.
I suspect that it might have something to do with byte alignment. Can it be somehow related to that?
I would love to hear some suggestions on this. Thanks in advance!
Is there any way to generate random numbers without duplication?
For instance I want to generate 50 random numbers from 1 to 100 no duplication, any way to do this or do I have to check every time incoming number is already created or not?
you can use shuffle as following code.
import 'dart:math';
var list = new List<int>.generate(10, (int index) => index); // [0, 1, 4]
list.shuffle();
print(list);
You can use Set. Each object can occur only once when using it. Just try this:
Set<int> setOfInts = Set();
while (setOfInts.length < 50) {
setOfInts.add(Random().nextInt(range) + 1);
}
You can read the documentation here: Set Doc
Here is an alternative that avoids creating an array of all the possible values, and avoids repeatedly looping until no collision occurs. It may be useful when there is a large range to select from.
import 'dart:math';
class RandomList {
static final _random = new Random();
static List<int> uniqueSample({int limit, int n}) {
final List<int> sortedResult = [];
final List<int> result = [];
for (int i = 0; i < n; i++) {
int rn = _random.nextInt(limit - i); // We select from a smaller list of available numbers each time
// Increment the number so that it picks from the remaining list of available numbers
int j = 0;
for (; j < sortedResult.length && sortedResult[j] <= rn; j++) rn++;
sortedResult.insert(j, rn);
result.add(rn);
}
return result;
}
}
I haven't tested it exhaustively but it seems to work.
There are Bollinger Bands with three RSI running in the basement.
I want to do a check on the signal in such a way that when 3 RSI struck the zone of the upper Bbands, there was a signal down and vice versa:
int start(){
double ma, stdev;
int i, limit, count=IndicatorCounted();
if(count<0) return(0);
limit=Bars-count;
if(limit>1) limit=Bars-1;
for(i=limit; i>=0; i--) {
RSI[i] =iRSI(Symbol(),Period(),rsi_period, PRICE_CLOSE,i);
RSI2[i]=iRSI(Symbol(),Period(),rsi_period_2,PRICE_CLOSE,i);
RSI3[i]=iRSI(Symbol(),Period(),rsi_period_3,PRICE_CLOSE,i);
}
for(i=limit; i>=0; i--) {
ma=iMAOnArray(RSI3,0,bb_period,0,0,i); // midle line
stdev=iStdDevOnArray(RSI3,0,bb_period,0,0,i); // dev
BBUP[i]=ma+bb_dev*stdev; // up line
BBDOWN[i]=ma-bb_dev*stdev; // down line
UP[i]=0;
DOWN[i]=0;
}
if(limit<Bars-1) limit++;
for(i=limit; i>0; i--) {
if(RSI[i] <= BBDOWN[i] && RSI[i+1] > BBDOWN[i+1] && RSI2[i] <= BBDOWN[i] && RSI2[i+1] > BBDOWN[i+1] && RSI3[i] <= BBDOWN[i] && RSI3[i+1] > BBDOWN[i+1]){
DOWN[i] = iLow(_Symbol, _Period, i);
}
if(RSI[i] >= BBUP[i] && RSI[i+1] < BBUP[i+1] &&W RSI2[i] >= BBUP[i] && RSI2[i+1] < BBUP[i+1] && RSI3[i] >= BBUP[i] && RSI3[i+1] < BBUP[i+1]){
UP[i]= iHigh(_Symbol, _Period, i);
}
}
The whole problem is that I have very crooked signals.
Appear where they should not be, and there is no where to be.
THE BEST PRACTICE:
Step 0: Let's first agree in written WHAT is the actual TARGET:
If the TARGET is to compute & paint on GUI the Bollinger Bands on RSI3[] values, the best way to do this is to use:
UPPER[i] = iBandsOnArray( RSI3, // ArrayAsSeries[]
array_calculation_depth, // reduce overheads
BB_MA_period, // BBands period
BB_StDev_MUL, // how many sigmas
BB_Zero_Shift, // #DEFINE BB_Zero_Shift 0
MODE_UPPER, // BBands upper line
i // shifting operator[i]
);
This way one may efficiently produce each of the { MODE_UPPER | MODE_MAIN | MODE_LOWER } Bollinger Bands lines here, consistently generated over dimension-less RSI3[] data, thus protecting the sense of any additive operations in signal-composition(s) with other, dimension-less data, as in { RSI2[], RSI[] }.
Step 1: visually check the lines to validate any signal-conditions:
Given the GUI shows lines accordingly, one may try to compose signal-conditions. The "hot"-bar [0] is a live-bar, where novice may encounter tricking signalling situations, if not handled with due professional care.
Step 2: implement signal-conditions in code:
Only after Step 0) & 1) took place and both meet one's own prior expectations, any code starts to make sense to get built.
From MQL4 docs https://docs.mql4.com/indicators/imaonarray
Unlike iMA(...), the iMAOnArray() function does not take data by
symbol name, timeframe, the applied price. The price data must be
previously prepared. The indicator is calculated from left to right.
To access to the array elements as to a series array (i.e., from right
to left), one has to use the ArraySetAsSeries() function.
RSI3 is currently orientated right to left (0 is most recent time point, limit is furthest element).
Same issue with iStdDevOnArray()
Fix those issues and it should work as you want. Whether there is any value in drawing Bollinger bands on RSI is another matter
Update
The function ArraySetAsSeries() can be used to swap the array between left-to-right and right-to-left
When you first initialise the RSI arrays ( in the OnInit() ) tell MetaTrader Terminal that they are timeseries.
ArraySetAsSeries(RSI1,True);
ArraySetAsSeries(RSI2,True);
ArraySetAsSeries(RSI3,True);
Then in main body, add ArraySetAsSeries(RSI3,False); before your second for loop to swap the array orientation. Then ArraySetAsSeries(RSI3,True); after the loop to restore the array orientation.
for(i=limit; i>=0; i--) {
RSI[i ] = iRSI(Symbol(),Period(),rsi_period,PRICE_CLOSE,i);
RSI2[i] = iRSI(Symbol(),Period(),rsi_period_2,PRICE_CLOSE,i);
RSI3[i] = iRSI(Symbol(),Period(),rsi_period_3,PRICE_CLOSE,i);
}
ArraySetAsSeries(RSI3,False);
for(i=limit; i>=0; i--) {
ma=iMAOnArray(RSI3,0,bb_period,0,0,i); // midle line
stdev=iStdDevOnArray(RSI3,0,bb_period,0,0,i); // dev
BBUP[i]=ma+bb_dev*stdev; // up line
BBDOWN[i]=ma-bb_dev*stdev; // down line
UP[i]=0;
DOWN[i]=0;
}
ArraySetAsSeries(RSI3,True);
if(limit<Bars-1) limit++;
for(i=limit; i>0; i--) {
if( RSI[i] <= BBDOWN[i] &&
RSI[i+1] > BBDOWN[i] &&
RSI2[i] <= BBDOWN[i] &&
RSI2[i+1] > BBDOWN[i] &&
RSI3[i] <= BBDOWN[i] &&
RSI3[i+1] > BBDOWN[i]) {
DOWN[i] = iLow(_Symbol, _Period, i);
}
if( RSI[i] >= BBUP[i] &&
RSI[i+1] < BBUP[i+1] &&
RSI2[i] >= BBUP[i] &&
RSI2[i+1] < BBUP[i+1] &&
RSI3[i] >= BBUP[i] &&
RSI3[i+1] < BBUP[i+1]) {
UP[i]= iHigh(_Symbol, _Period, i);
}
}
Basic indicator structure
You need to go through the MQL4 Documentation and learn the proper structure of an indicator. There needs to be an OnInit() function where you initialise values. Then an OnCalculate() function where you fill the indicator buffers.
//+-----------------------------------------------------------------+
//| Custom indicator initialization function |
//+-----------------------------------------------------------------+
int OnInit()
{
//--- indicator buffers mapping
ArraySetAsSeries(RSI3,True);
//---
return(INIT_SUCCEEDED);
}
//+-----------------------------------------------------------------+
//| Custom indicator iteration function |
//+-----------------------------------------------------------------+
int OnCalculate(const int rates_total,
const int prev_calculated,
const datetime& time[],
const double& open[],
const double& high[],
const double& low[],
const double& close[],
const long& tick_volume[],
const long& volume[],
const int& spread[])
{
// Do your calculations here
//--- return value of prev_calculated for next call
return(rates_total);
}
If you use iBandsOnArray() to calculate Bollinger bands you won't need to swap the array direction after it is set in OnInit()
If the indicator is compiling but crashing, you will need to debug it. Simplest way is to look at the errors in the log and add PrintFormat() statements throughout your code so you can see what the indicator is doing at different points and see where it crashes.
local function fShallowCopy(tData)
local tOutput = {}
for k,v in ipairs(tData) do
tOutput[k] = v
end
return tOutput
end
local function fLexTblSort(tA,tB) --sorter for tables
for i=1,#tA do
if tA[i]~=tB[i] then
return tA[i]<tB[i]
end
end
return false
end
function fBWT(tData)
--setup--
local iSize = #tData
local tSolution = {}
local tSolved = {}
--key table--
for n=1,iSize do
tData[iSize] = fRemove(tData,1)
tSolution[n] = fShallowCopy(tData)
end
table.sort(tSolution,fLexTblSort)
--encode output--
for i=1,iSize do
tSolved[i] = tSolution[i][iSize]
end
--finalize--
for i=1,iSize do
if fIsEqual(tSolution[i],tData) then
return i,tSolved
end
end
return false
end
Above is my current code for achieving BWT encoding in Lua. The issue is because of the size of the tables and lengths of loops it takes a long time to run. For a 1000 character input the average encoding time is about 1.15 seconds. Does anyone have suggestions for making a faster BWT encoding function?
the biggest slowdowns appear to be in fLexTblSort and fShallowCopy. I have included both above the BWT function as well.
If I see right, your algorithm has complexity O(n^2 log n), if the sort is quicksort. The comparator function fLexTblSort takes O(n) itself for each pair of values you compare.
As I checked with my implementation from few years back, I see possible space to improve. You create all the possible rotations of the tData, which takes also a lot of time. I used only single data block and I stored only starting positions of particular rotations. You also use a lot of loops which can shrink into less.
Mine implementation was in C, but the concept can be used also in Lua. The idea in some hybrid pseudocode between your Lua and C.
function fBWT(tData)
local n = #tData
local tSolution = {}
for(i = 0; i < n; i++)
tSolution[i] = i;
--table.sort(tSolution, fLexTblSort)
quicksort(tData, n, tSolution, 0, n)
for(i = 0; i < n; i++){
tSolved[i] = tData[(tSolution[i]+n-1)%n];
if( tSolution[i] == 0 )
I = i;
}
return I, tSolved
end
You will also need your own sort function, because the standard does not offer enough flexibility for this magic. Quicksort is a good idea (you might avoid some of the arguments, but I pasted just the C version I was using):
void swap(int array[], int left, int right){
int tmp = array[right];
array[right] = array[left];
array[left] = tmp;
}
void quicksort(uint8_t data[], int length, int array[], int left, int right){
if(left < right){
int boundary = left;
for(int i = left + 1; i < right; i++){
if( offset_compare(data, length, array, i, left) < 0 ){
swap(array, i, ++boundary);
}
}
swap(array, left, boundary);
quicksort(data, length, array, left, boundary);
quicksort(data, length, array, boundary + 1, right);
}
}
The last step is your own comparator function (similar to your original, but working on the rotations, again in C):
/**
* compare one string (fixed length) with different rotations.
*/
int offset_compare(uint8_t *data, int length, int *array, int first, int second){
int res;
for(int i = 0; i < length; i++){
res = data[(array[first]+i)%length] - data[(array[second]+i)%length];
if( res != 0 ){
return res;
}
}
return 0;
}
This is the basic idea I came up with few years ago and which worked for me. Let me know if there is something not clear or some mistake.
my program is Directx Program that draws a container cube within it smaller cubes....these smaller cubes fall by time i hope you understand what i mean...
The program isn't complete yet ...it should draws the container only ....but it draws nothing ...only the background color is visible... i only included what i think is needed ...
this is the routines that initialize the program
bool Game::init(HINSTANCE hinst,HWND _hw){
Directx11 ::init(hinst , _hw);
return LoadContent();}
Directx11::init()
bool Directx11::init(HINSTANCE hinst,HWND hw){
_hinst=hinst;_hwnd=hw;
RECT rc;
GetClientRect(_hwnd,&rc);
height= rc.bottom - rc.top;
width = rc.right - rc.left;
UINT flags=0;
#ifdef _DEBUG
flags |=D3D11_CREATE_DEVICE_DEBUG;
#endif
HR(D3D11CreateDevice(0,_driverType,0,flags,0,0,D3D11_SDK_VERSION,&d3dDevice,&_featureLevel,&d3dDeviceContext));
if (d3dDevice == 0 || d3dDeviceContext == 0)
return 0;
DXGI_SWAP_CHAIN_DESC sdesc;
ZeroMemory(&sdesc,sizeof(DXGI_SWAP_CHAIN_DESC));
sdesc.Windowed=true;
sdesc.BufferCount=1;
sdesc.BufferDesc.Format=DXGI_FORMAT_R8G8B8A8_UNORM;
sdesc.BufferDesc.Height=height;
sdesc.BufferDesc.Width=width;
sdesc.BufferDesc.Scaling=DXGI_MODE_SCALING_UNSPECIFIED;
sdesc.BufferDesc.ScanlineOrdering=DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
sdesc.OutputWindow=_hwnd;
sdesc.BufferDesc.RefreshRate.Denominator=1;
sdesc.BufferDesc.RefreshRate.Numerator=60;
sdesc.Flags=0;
sdesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
if (m4xMsaaEnable)
{
sdesc.SampleDesc.Count=4;
sdesc.SampleDesc.Quality=m4xMsaaQuality-1;
}
else
{
sdesc.SampleDesc.Count=1;
sdesc.SampleDesc.Quality=0;
}
IDXGIDevice *Device=0;
HR(d3dDevice->QueryInterface(__uuidof(IDXGIDevice),reinterpret_cast <void**> (&Device)));
IDXGIAdapter*Ad=0;
HR(Device->GetParent(__uuidof(IDXGIAdapter),reinterpret_cast <void**> (&Ad)));
IDXGIFactory* fac=0;
HR(Ad->GetParent(__uuidof(IDXGIFactory),reinterpret_cast <void**> (&fac)));
fac->CreateSwapChain(d3dDevice,&sdesc,&swapchain);
ReleaseCOM(Device);
ReleaseCOM(Ad);
ReleaseCOM(fac);
ID3D11Texture2D *back = 0;
HR(swapchain->GetBuffer(0,__uuidof(ID3D11Texture2D),reinterpret_cast <void**> (&back)));
HR(d3dDevice->CreateRenderTargetView(back,0,&RenderTarget));
D3D11_TEXTURE2D_DESC Tdesc;
ZeroMemory(&Tdesc,sizeof(D3D11_TEXTURE2D_DESC));
Tdesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
Tdesc.ArraySize = 1;
Tdesc.Format= DXGI_FORMAT_D24_UNORM_S8_UINT;
Tdesc.Height= height;
Tdesc.Width = width;
Tdesc.Usage = D3D11_USAGE_DEFAULT;
Tdesc.MipLevels=1;
if (m4xMsaaEnable)
{
Tdesc.SampleDesc.Count=4;
Tdesc.SampleDesc.Quality=m4xMsaaQuality-1;
}
else
{
Tdesc.SampleDesc.Count=1;
Tdesc.SampleDesc.Quality=0;
}
HR(d3dDevice->CreateTexture2D(&Tdesc,0,&depthview));
HR(d3dDevice->CreateDepthStencilView(depthview,0,&depth));
d3dDeviceContext->OMSetRenderTargets(1,&RenderTarget,depth);
D3D11_VIEWPORT vp;
vp.TopLeftX=0.0f;
vp.TopLeftY=0.0f;
vp.Width = static_cast <float> (width);
vp.Height= static_cast <float> (height);
vp.MinDepth = 0.0f;
vp.MaxDepth = 1.0f;
d3dDeviceContext -> RSSetViewports(1,&vp);
return true;
SetBuild() Prepare the matrices inside the container for the smaller cubes ....i didnt program it to draw the smaller cubes yet
and this the function that draws the scene
void Game::Render(){
d3dDeviceContext->ClearRenderTargetView(RenderTarget,reinterpret_cast <const float*> (&Colors::LightSteelBlue));
d3dDeviceContext->ClearDepthStencilView(depth,D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL,1.0f,0);
d3dDeviceContext-> IASetInputLayout(_layout);
d3dDeviceContext-> IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
d3dDeviceContext->IASetIndexBuffer(indices,DXGI_FORMAT_R32_UINT,0);
UINT strides=sizeof(Vertex),off=0;
d3dDeviceContext->IASetVertexBuffers(0,1,&vertices,&strides,&off);
D3DX11_TECHNIQUE_DESC des;
Tech->GetDesc(&des);
Floor * Lookup; /*is a variable to Lookup inside the matrices structure (Floor Contains XMMATRX Piese[9])*/
std::vector<XMFLOAT4X4> filled; // saves the matrices of the smaller cubes
XMMATRIX V=XMLoadFloat4x4(&View),P = XMLoadFloat4x4(&Proj);
XMMATRIX vp = V * P;XMMATRIX wvp;
for (UINT i = 0; i < des.Passes; i++)
{
d3dDeviceContext->RSSetState(BuildRast);
wvp = XMLoadFloat4x4(&(B.Memory[0].Pieces[0])) * vp; // Loading The Matrix at translation(0,0,0)
HR(ShadeMat->SetMatrix(reinterpret_cast<float*> ( &wvp)));
HR(Tech->GetPassByIndex(i)->Apply(0,d3dDeviceContext));
d3dDeviceContext->DrawIndexed(build_ind_count,build_ind_index,build_vers_index);
d3dDeviceContext->RSSetState(PieseRast);
UINT r1=B.GetSize(),r2=filled.size();
for (UINT j = 0; j < r1; j++)
{
Lookup = &B.Memory[j];
for (UINT r = 0; r < Lookup->filledindeces.size(); r++)
{
filled.push_back(Lookup->Pieces[Lookup->filledindeces[r]]);
}
}
for (UINT j = 0; j < r2; j++)
{
ShadeMat->SetMatrix( reinterpret_cast<const float*> (&filled[i]));
Tech->GetPassByIndex(i)->Apply(0,d3dDeviceContext);
d3dDeviceContext->DrawIndexed(piese_ind_count,piese_ind_index,piese_vers_index);
}
}
HR(swapchain->Present(0,0));}
thanks in Advance
One bug in your program appears to be that you're using i, the index of the current pass, as an index into the filled vector, when you should apparently be using j.
Another apparent bug is that in the loop where you are supposed to be iterating over the elements of filled, you're not iterating over all of them. The value r2 is set to the size of filled before you append anything to it during that pass. During the first pass this means that nothing will be drawn by this loop. If your technique only has one pass then this means that the second DrawIndexed call in your code will never be executed.
It also appears you should be only adding matrices to filled once, regardless of the number of the passes the technique has. You should consider if your code is actually meant to work with techniques with multiple passes.