Nekto Finkelmaer
Nekto Finkelmaer личный блог
21 марта 2024, 08:58

Робот для торговли спреда внутри канала, пробоя или отбоя от уровня (с исходниками на Java Script)

Скрипт в руки — деньги в карман.

Инструкция:
1. Бери «Скрипт».
2. Пиши «Тикер» из фондовой секции ММВБ.
3. Жми «График».
Вуаля… ваш брокерский счет наливается прибылью.

Чем жирнее цена, тем жирнее уровень.
Пользуйся и твоя эквити будет гладкая и больше чем вчера.

Робот для торговли спреда внутри канала, пробоя или отбоя от уровня (с исходниками на Java Script)

ПС: График влево.
Данные ММВБ с задержкой 15 минут.

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
</head>
<body>

<form name="search">
    <input type="text" name="key" placeholder="Тикер" id="key"/>
    <input type="button" name="buttonChart" value="График" />
</form>
<div id="printBlock"></div>
<canvas id="chart" width="4000" height="600"></canvas>
<script>
const keyBox = document.search.key;
const keyButton = document.search.buttonChart;
 
 function DrawChart(prices,minPrice,maxPrice,maxVolume,ZZ,ZZDay){

	var chart = document.getElementById("chart");
	
	
	if (chart.getContext) {
		var ctx = chart.getContext("2d");
		ctx.lineWidth=1;
		Point = 0;
		for (let i = prices. <a name="cut"></a> length-1; i >= 0; i--) { 
			var K=600/(maxPrice-minPrice);
			var pOpen = Math.trunc((prices[i].Open-minPrice)*K);
			var pClose = Math.trunc((prices[i].Close-minPrice)*K);
			
			var pMin = Math.trunc((prices[i].Low-minPrice)*K);
			var pMax = Math.trunc((prices[i].High-minPrice)*K);
			
			var dStart = 600-Math.max(pOpen,pClose);
			var dFinish = 600-Math.min(pOpen,pClose);
			
			var dMin = 600-pMin;
			var dMax = 600-pMax;
			
			var pVolume = Math.trunc((prices[i].Volume)/maxVolume*100);
			var dVolume = 600-pVolume;
			
			var AA = prices[i].Close - prices[i].Open;
			
			//ctx.beginPath();
			if (pOpen==pClose) {
				
				ctx.fillStyle = "rgb(0,0,0)";
				dFinish = dStart+1;
				//console.log("-"+(Point*4)+" "+dStart+" "+dFinish + " "+AA+" "+pOpen+" "+pClose+" "+K);
				
			}
			else {
				
				if (prices[i].Open>prices[i].Close) {
					ctx.fillStyle = "rgb(200,0,0)";
				}
				else{
					ctx.fillStyle = "rgb(0,200,0)";
				}
				
			}
			
			
			if (Point==0) {
				ctx.fillRect(Point, dStart, 40, 1);
				
				ctx.textBaseline = "bottom";
				ctx.font = "bold 8px Arial";
				
				ctx.fillText(prices[i].Close, Point, dStart-2);
				
				Point = Point+11;
			}
			
			//console.log(""+(Point*4)+" "+dStart+" "+dFinish + " "+AA+" "+pOpen+" "+pClose+" "+K);
			ctx.fillRect(Point*4, dStart, 3, dFinish-dStart);
			
			ctx.fillStyle = ctx.fillStyle.replace(")",",0.7)");
			
			//console.log(""+prices[i].Volume+" "+maxVolume + " "+pVolume+" "+dVolume+" "+ctx.fillStyle);
			
			ctx.fillRect(Point*4, dVolume, 3, 600-dVolume);
			
			ctx.fillStyle = "rgb(0,0,0)";
			ctx.fillRect(Point*4+1, dMax, 1, dStart-dMax);
			ctx.fillRect(Point*4+1, dFinish, 1, dMin-dFinish);
			Point ++;
		}
		
		
		
		DrawZZ(ZZ,ctx,prices,maxPrice,minPrice);
		ctx.lineWidth=2;
		DrawZZ(ZZDay,ctx,prices,maxPrice,minPrice);
		
		var priceLevel = [];
		
		ctx.lineWidth=1;
		ctx.strokeStyle = "rgb(0,0,200,0.3)";
		DrawK(ZZ,ctx,prices,maxPrice,minPrice,1,3,priceLevel);
		DrawK(ZZ,ctx,prices,maxPrice,minPrice,3,5,priceLevel);
		DrawK(ZZ,ctx,prices,maxPrice,minPrice,1,5,priceLevel);
		
		DrawK(ZZ,ctx,prices,maxPrice,minPrice,2,4,priceLevel);
		DrawK(ZZ,ctx,prices,maxPrice,minPrice,4,6,priceLevel);
		DrawK(ZZ,ctx,prices,maxPrice,minPrice,2,6,priceLevel);
		
		ctx.lineWidth=2;
		
		DrawK(ZZDay,ctx,prices,maxPrice,minPrice,1,3,priceLevel);
		DrawK(ZZDay,ctx,prices,maxPrice,minPrice,3,5,priceLevel);
		DrawK(ZZDay,ctx,prices,maxPrice,minPrice,1,5,priceLevel);
		
		DrawK(ZZDay,ctx,prices,maxPrice,minPrice,2,4,priceLevel);
		DrawK(ZZDay,ctx,prices,maxPrice,minPrice,4,6,priceLevel);
		DrawK(ZZDay,ctx,prices,maxPrice,minPrice,2,6,priceLevel);
		
		priceLevel.sort(function(a,b){ 
							if (a.Price<b.Price) return -1; else if (a.Price>b.Price) return 1; else return 0;
						});
		
		
		priceLevelGroup = [];
		maxVolume = 0;
		for (let i = 0; i < priceLevel.length; i++) {
			
			console.log(""+priceLevel[i].Price+" "+priceLevel[i].Volume);
			
			if (i==0) {
				priceLevelGroup[0] = {Price:priceLevel[i].Price,Volume:priceLevel[i].Volume};
				
			}
			else{
				if (priceLevel[i].Price/priceLevelGroup[priceLevelGroup.length-1].Price-1<0.003) {
					
						priceLevelGroup[priceLevelGroup.length-1].Price = 
											(priceLevel[i].Volume*priceLevel[i].Price
											+priceLevelGroup[priceLevelGroup.length-1].Volume*priceLevelGroup[priceLevelGroup.length-1].Price)
											/(priceLevel[i].Volume+priceLevelGroup[priceLevelGroup.length-1].Volume);
						priceLevelGroup[priceLevelGroup.length-1].Volume = priceLevelGroup[priceLevelGroup.length-1].Volume+priceLevel[i].Volume;
						
				}
				else{
					priceLevelGroup[priceLevelGroup.length] = {Price:priceLevel[i].Price,Volume:priceLevel[i].Volume};
				}
						
			};
			if (priceLevelGroup[priceLevelGroup.length-1].Volume>maxVolume){
				maxVolume = priceLevelGroup[priceLevelGroup.length-1].Volume;
			}
			
		}
		
		for (let i = 0; i < priceLevelGroup.length; i++) {
			
			
			pOpen = Math.trunc((priceLevelGroup[i].Price-minPrice)*K);
			
			dStart = 600-pOpen;
			
			ctx.fillRect(0, dStart, 40, 1);
				
			ctx.textBaseline = "bottom";
			
			ctx.font = ""+(Math.trunc(priceLevelGroup[i].Volume/maxVolume*12)+6)+"px Arial";
			
			console.log("g "+maxVolume+" "+priceLevelGroup[i].Volume+" "+ctx.font+" "+(Math.trunc(priceLevelGroup[i].Volume/maxVolume*12)+6));
			
			//console.log("g "+priceLevelGroup[i].Price+" "+priceLevelGroup[i].Volume+" "+ctx.font+" "+(Math.trunc(priceLevelGroup[i].Volume/maxVolume*12)+6));
			
			percent = Math.trunc((prices[prices.length-1].Close - priceLevelGroup[i].Price)/prices[prices.length-1].Close*10000)/100;
			if (percent<0) {percent=-percent;ctx.fillStyle = "rgb(100,150,100)";}
			else {ctx.fillStyle = "rgb(150,100,100)"};
			ctx.fillText(""+Math.trunc(priceLevelGroup[i].Price*100)/100+" ("+percent+"%)", 0, dStart-1);
				
		}
		
	}
 }
 
 function DrawZZ(ZZ,ctx,prices,maxPrice,minPrice){
		
		ctx.fillStyle = "rgb(0,0,0,0.7)";
		ctx.beginPath();
		
		for (let i = 0; i < ZZ.length; i++) {
			
			Point = (prices.length - ZZ[i].Point+10)*4+1;
			var K=600/(maxPrice-minPrice);
			pPrice = Math.trunc((ZZ[i].price-minPrice)*K);
			dStart = 600-pPrice;
			
			//console.log(""+ZZ[i].price+" "+dStart+ " "+ZZ[i].Point+" "+ZZ[i].T);
			
			if (i==0) {
				ctx.moveTo(Point,dStart);
			} else {
				ctx.lineTo(Point,dStart);
			}
		}
		ctx.stroke();
 }

function DrawK(ZZ,ctx,prices,maxPrice,minPrice,p1,p2,priceLevel){
		
		
		if (ZZ.length-p1<0 || ZZ.length-p2<0) {return};
		
		var K=600/(maxPrice-minPrice);
		
		first = ZZ.length - p1;
		second = ZZ.length - p2;
		
		//console.log(""+first+" "+second+" "+ZZ.length);
		
		fPoint = (prices.length-ZZ[first].Point+10)*4+1;
		sPoint = (prices.length-ZZ[second].Point+10)*4+1;
			
		ePrice=ZZ[second].price+(prices.length-ZZ[second].Point)*(ZZ[first].price-ZZ[second].price)/(ZZ[first].Point-ZZ[second].Point)
		
		priceLevel[priceLevel.length] = {Price:ePrice,Volume:(ZZ[second].Volume+ZZ[first].Volume)};
		priceLevel[priceLevel.length] = {Price:ZZ[first].price,Volume:(ZZ[first].Volume)};
		priceLevel[priceLevel.length] = {Price:ZZ[second].price,Volume:(ZZ[second].Volume)};
		
		
		//console.log(""+ZZ[first].Point+" "+ZZ[second].Point+" "+" "+prices.length+" "+ZZ[first].price+" "+ZZ[second].price+" "+ePrice);
		
		fPrice = Math.trunc((ZZ[first].price-minPrice)*K);
		sPrice = Math.trunc((ZZ[second].price-minPrice)*K);
		ePrice = Math.trunc((ePrice-minPrice)*K);
		
		dStart = 600-sPrice;
		dFinish = 600-ePrice;
		
		
		//console.log(""+first+" "+second+" "+fPrice+" "+sPrice+" "+ePrice);
		
		//ctx.fillStyle = "rgb(0,0,255,0.7)";
		//console.log(""+ctx.fillStyle);
		ctx.beginPath();
		ctx.moveTo(sPoint,dStart);
		ctx.lineTo(40,dFinish);
		ctx.stroke();
		
		ctx.beginPath();
		ctx.moveTo(sPoint,dStart);
		ctx.lineTo(40,dStart);
		ctx.stroke();
		
		ctx.beginPath();
		ctx.moveTo(fPoint,600-fPrice);
		ctx.lineTo(40,600-fPrice);
		ctx.stroke();
		
 }
 
 function FillArray (data){

	var prices = [];
	var pricesDay = [];
	var ZZ = [];
	var ZZDay = [];
	var minPrice = 9999999;
	var maxPrice = 0;
	var maxVolume = 0;
	
	let md = data['candles']['data'];
	 
	for (let i = 0; i < md.length; i++) {
		var cl = prices.length;
		prices[cl] = [];
		prices[cl] = {Period:md[i][6], Open:md[i][0], Close:md[i][1],Low:md[i][3], High:md[i][2], Volume:md[i][5], Period:md[i][6]}
		if (minPrice>prices[cl].Low) {
				minPrice = prices[cl].Low;
		}
		if (maxPrice<prices[cl].High) {
				maxPrice = prices[cl].High;
		}
		if (maxVolume<prices[cl].Volume) {
				maxVolume = prices[cl].Volume;
		}
		
		var cDay = prices[cl].Period;
		cDay = cDay.substring(0,10);
		
		
		PosDay=pricesDay.findIndex(item => item.Period == cDay);
		if (PosDay==-1) {PosDay=pricesDay.length; pricesDay[PosDay]={Period:cDay,High:prices[cl].High,Low:prices[cl].Low,PeriodHi:i,PeriodLow:i,Volume:prices[cl].Volume}}
		if (pricesDay[PosDay].High<prices[cl].High) {pricesDay[PosDay].High=prices[cl].High;pricesDay[PosDay].PeriodHi=cl;}
		if (pricesDay[PosDay].Low>prices[cl].Low) {pricesDay[PosDay].Low=prices[cl].Low;pricesDay[PosDay].PeriodLow=cl;}
		pricesDay[PosDay].Volume = pricesDay[PosDay].Volume+prices[cl].Volume;
		
		if (cl>1) {
			if (ZZ.length == 0) {
				ZZ[0] = {price:(prices[cl-2].Open>prices[cl].Close ? prices[cl-2].High:prices[cl-2].Low), 
								Point:cl-2, 
								T:(prices[cl-2].Open>prices[cl].Close ? -1:1),
								Volume:prices[cl-2].Volume}
				
				//console.log("f "+ZZ[ZZ.length-1].price+" "+" "+ZZ[ZZ.length-1].Point+" "+ZZ[ZZ.length-1].T);
				
			} else {
				if (ZZ[ZZ.length-1].T == 1) { 
					//console.log("up "+ZZ[ZZ.length-1].price+" "+" "+ZZ[ZZ.length-1].Point+" "+ZZ[ZZ.length-1].T);
				
					if (prices[cl-2].High<prices[cl].High || prices[cl-1].High<prices[cl].High || prices[cl-2].Low<prices[cl].Low || prices[cl-1].Low<prices[cl].Low) {}
					else {
							ZZ[ZZ.length]={price:(Math.max(prices[cl-2].High,prices[cl-1].High)),
									       Point:(prices[cl-2].High>prices[cl-1].High ? cl-2:cl-1),
										   T:-1,
										   Volume:(prices[cl-2].High>prices[cl-1].High ? prices[cl-2].Volume:prices[cl-1].Volume)}
							
							//console.log("up "+ZZ[ZZ.length-1].price+" "+" "+ZZ[ZZ.length-1].Point+" "+ZZ[ZZ.length-1].T);
						}
					} 
				else {
					if (ZZ[ZZ.length-1].T == -1) { 
						if (prices[cl-2].Low>prices[cl].Low || prices[cl-1].Low>prices[cl].Low || prices[cl-2].High>prices[cl].High || prices[cl-1].High>prices[cl].High) {}
						else {
							ZZ[ZZ.length]={price:(Math.min(prices[cl-2].Low,prices[cl-1].Low)),
										   Point:(prices[cl-2].Low<prices[cl-1].Low ? cl-2:cl-1),
										   T:1,
										   Volume:(prices[cl-2].Low<prices[cl-1].Low ? prices[cl-2].Volume:prices[cl-1].Volume)}
							//console.log("dw "+ZZ[ZZ.length-1].price+" "+" "+ZZ[ZZ.length-1].Point+" "+ZZ[ZZ.length-1].T);
						}
						 
					}
				}
				
			}
		}
	}
	
	for (let cl = 0; cl < pricesDay.length; cl++) {
		//console.log(""+pricesDay[cl].Period+" "+pricesDay[cl].High+" "+pricesDay[cl].Low+" "+pricesDay[cl].Volume+" "+pricesDay[cl].PeriodHi+" "+pricesDay[cl].PeriodLow);
		
		if (cl>1) {
			if (ZZDay.length == 0) {
				ZZDay[0] = {price:(pricesDay[cl-2].Open>pricesDay[cl].Close ? pricesDay[cl-2].High:pricesDay[cl-2].Low), 
							Point:(pricesDay[cl-2].Open>pricesDay[cl].Close ? pricesDay[cl-2].PeriodHi:pricesDay[cl-2].PeriodLow), 
							T:(pricesDay[cl-2].Open>pricesDay[cl].Close ? -1:1),
							Volume:prices[cl-2].Volume}
				
				//console.log("f "+ZZDay[ZZDay.length-1].price+" "+" "+ZZDay[ZZDay.length-1].Point+" "+ZZDay[ZZDay.length-1].T);
				
			} else {
				if (ZZDay[ZZDay.length-1].T == 1) { 
					//console.log("up "+ZZDay[ZZDay.length-1].price+" "+" "+ZZDay[ZZDay.length-1].Point+" "+ZZDay[ZZDay.length-1].T);
				
					if (pricesDay[cl-2].High<pricesDay[cl].High || pricesDay[cl-1].High<pricesDay[cl].High || pricesDay[cl-2].Low<pricesDay[cl].Low || pricesDay[cl-1].Low<pricesDay[cl].Low) {}
					else {
							ZZDay[ZZDay.length]={price:(Math.max(pricesDay[cl-2].High,pricesDay[cl-1].High)),
											     Point:(pricesDay[cl-2].High>pricesDay[cl-1].High ? pricesDay[cl-2].PeriodHi:pricesDay[cl-1].PeriodHi),
												 T:-1,
												 Volume:(pricesDay[cl-2].High>pricesDay[cl-1].High ? pricesDay[cl-2].Volume:pricesDay[cl-1].Volume)}
							
							//console.log("up "+ZZDay[ZZDay.length-1].price+" "+" "+ZZDay[ZZDay.length-1].Point+" "+ZZDay[ZZDay.length-1].T);
						}
					} 
				else {
					if (ZZDay[ZZDay.length-1].T == -1) { 
						if (pricesDay[cl-2].Low>pricesDay[cl].Low || pricesDay[cl-1].Low>pricesDay[cl].Low || pricesDay[cl-2].High>pricesDay[cl].High || pricesDay[cl-1].High>pricesDay[cl].High) {}
						else {
							ZZDay[ZZDay.length]={price:(Math.min(pricesDay[cl-2].Low,pricesDay[cl-1].Low)),
												 Point:(pricesDay[cl-2].Low<pricesDay[cl-1].Low ? pricesDay[cl-2].PeriodLow:pricesDay[cl-1].PeriodLow),
												 T:1,
												 Volume:(pricesDay[cl-2].Low<pricesDay[cl-1].Low ? pricesDay[cl-2].Volume:pricesDay[cl-1].Volume)}
							//console.log("dw "+ZZDay[ZZDay.length-1].price+" "+" "+ZZDay[ZZDay.length-1].Point+" "+ZZDay[ZZDay.length-1].T);
						}
						 
					}
				}
				
			}
		}
	}
	
	DrawChart(prices,minPrice,maxPrice,maxVolume,ZZ,ZZDay);
	return prices;
 }
 
 function strRight(n,str){
   return str.substring(str.length-n,str.length);
 }  
// обработчик изменения текста
function onchange(e){
    // получаем элемент printBlock
    const printBlock = document.getElementById("printBlock");
	const tiker = document.getElementById("key").value;
    // получаем новое значение
    const val = tiker;
    // установка значения
    printBlock.textContent = printBlock.textContent+" "+tiker;
	
	
	var URL = "https://iss.moex.com/iss/engines/stock/markets/shares/securities/<TIKER>/candles.json?from=<DateFrom>&interval=60";
	
	URL = URL.replace("<TIKER>", val);
	
	var now = new Date();
	now.setDate(now.getDate() - 45);
	console.log(now);

	var Month=now.getMonth()+1;
	var year=now.getFullYear();
	
	//if (Month<0) {Month=12+Month+1; year--;};
	var startdata = (year).toString()+"-"+strRight(2,"0"+Month.toString())+"-"+strRight(2,"0"+now.getDate().toString());
	
	URL = URL.replace("<DateFrom>", startdata);
	console.log(URL);
	fetch(URL)
		.then(function (response) {
			return response.json();
		})
		.then(function (data) {
			
			FillArray(data);
			
		})
  
}


//keyBox.addEventListener("change", onchange);
keyButton.addEventListener("click", onchange);
</script>
</body>
</html>
3 Комментария
  • Tema ☑️
    21 марта 2024, 09:03
    С таким роботом можно все деньги с рынка выкачать

Активные форумы
Что сейчас обсуждают

Старый дизайн
Старый
дизайн