Thursday, February 19, 2026
Kinstra Trade
  • Home
  • Bitcoin
  • Altcoin
    • Altcoin
    • Ethereum
    • Crypto Exchanges
  • Trading
  • Blockchain
  • NFT
  • Metaverse
  • DeFi
  • Web3
  • Scam Alert
  • Analysis
Crypto Marketcap
  • Home
  • Bitcoin
  • Altcoin
    • Altcoin
    • Ethereum
    • Crypto Exchanges
  • Trading
  • Blockchain
  • NFT
  • Metaverse
  • DeFi
  • Web3
  • Scam Alert
  • Analysis
No Result
View All Result
Kinstra Trade
No Result
View All Result
Home Trading News Forex

How to setup Grid Copier with Google Apps Script (step-by-step) – Other – 18 February 2026

February 18, 2026
in Forex
Reading Time: 8 mins read
A A
0
How to setup Grid Copier with Google Apps Script (step-by-step) – Other – 18 February 2026
Share on FacebookShare on Twitter


Why do we want Google Apps Script?

To trade commerce knowledge between separate MetaTrader terminals, a easy relay server is required. Google Apps Script acts as a free middleman that transfers commerce occasions from the Grasp account to the Slave account. It ensures dependable supply of occasions even after web interruptions or terminal restarts and doesn’t require a VPS or devoted server.

Find out how to create and deploy Google Apps Script

Go to https://script.google.com and Click on Begin scripting

Click on New challenge

Delete the default code and paste the script offered under the instruction steps

Press Ctrl + S to save lots of the challenge (the highest menu will grow to be lively)

Click on Deploy within the top-right nook and choose New deployment

Within the opened window, click on Choose sort (⚙️) and select Net app

In the Description subject, enter Model 1 (any textual content is okay). Set Who has entry to Anybody and depart Execute as unchanged

Click on Deploy – your Apps Script URL shall be generated. Copy and paste this URL into the EA enter settings

const API_KEY   = ‘I_AM_API_KEY’;


const MAX_PRUNE = 200;


const CONSUMER_TTL_MS = 6 * 60 * 60 * 1000;


const MAX_CONSUMERS_PER_CHANNEL = 50;



operate doPost(e) {
  const lock = LockService.getScriptLock();
  let locked = false;

  attempt {
    lock.waitLock(10000);
    locked = true;

    if (!e || !e.postData || !e.parameter) return _resp({ okay:false, error:‘no knowledge’ });

    const key = (e.parameter.key || ”).toString();
    if (key !== API_KEY) return _resp({ okay:false, error:‘forbidden’ });

    const channel  = (e.parameter.channel || ‘default’).toString();
    const client = (e.parameter.client || ”).toString();
    const c        = client || ‘single’;

    const retailer = PropertiesService.getScriptProperties();

    
    let uncooked = e.postData.contents || ‘{}’;
    uncooked = uncooked.substitute(/[u0000-u001F]+$/g, ”);

    let physique;
    attempt {
      physique = JSON.parse(uncooked);
    } catch (parseErr) {
      return _resp({ okay:false, error:‘dangerous json’, particulars:String(parseErr) });
    }

    
    
    _touchConsumerFast(retailer, channel, c);

    
    if (physique && physique.motion === ‘ack’) {
      const lastId = Quantity(physique.last_id || 0);
      if (!lastId) return _resp({ okay:false, error:‘dangerous ack’ });

      retailer.setProperty(_ackKey(channel, c), String(lastId));

      
      _pruneByMinAckFast(retailer, channel);

      return _resp({ okay:true, ack:lastId });
    }

    
    const nextId = _nextSeq(retailer, channel);

    physique.id = nextId;
    physique.server_time_ms = Date.now();

    
    retailer.setProperty(_evKey(channel, nextId), JSON.stringify(physique));

    
    const minKey = _minKey(channel);
    const curMin = Quantity(retailer.getProperty(minKey) || ‘0’);
    if (!curMin) retailer.setProperty(minKey, String(nextId));

    return _resp({ okay:true, last_id: nextId });

  } catch (err) {
    return _resp({
      okay:false,
      error:‘exception’,
      message:String(err),
      stack:(err && err.stack) ? String(err.stack) : ”
    });
  } lastly {
    if (locked) {
      attempt { lock.releaseLock(); } catch(_) {}
    }
  }
}

operate doGet(e) {
  const lock = LockService.getScriptLock();
  let locked = false;

  attempt {
    lock.waitLock(10000);
    locked = true;

    if (!e || !e.parameter) return _resp({ okay:false, error:‘no params’ });

    const key = (e.parameter.key || ”).toString();
    if (key !== API_KEY) return _resp({ okay:false, error:‘forbidden’ });

    const channel  = (e.parameter.channel || ‘default’).toString();
    const client = (e.parameter.client || ”).toString();
    const c        = client || ‘single’;
    const restrict    = Math.max(1, Math.min(100, Quantity(e.parameter.restrict || 20)));

    const retailer = PropertiesService.getScriptProperties();

    
    
    _touchConsumerFast(retailer, channel, c);

    const minId = Quantity(retailer.getProperty(_minKey(channel)) || ‘0’);
    const seq   = Quantity(retailer.getProperty(_seqKey(channel)) || ‘0’);

    const ackKey = _ackKey(channel, c);
    let ack = Quantity(retailer.getProperty(ackKey) || ‘0’);

    
    if (minId > 0) {
      const floorAck = Math.max(0, minId – 1);
      if (ack < floorAck) {
        ack = floorAck;
        retailer.setProperty(ackKey, String(ack));
      }
    }

    
    const mode = (e.parameter.mode || ”).toString();
    if (mode === ‘well being’ || mode === ‘debug’) {
      const shoppers = _listActiveConsumersFast(retailer, channel);
      const minAck = _minAckFast(retailer, channel, shoppers);
      const out = { okay:true, channel, client:c, ack, seq, min_id:minId, active_consumers:shoppers, min_ack:minAck };

      if (mode === ‘debug’) {
        
        const seen = {};
        for (const cc of shoppers) ‘0’);
        
        out.seen = seen;
      }
      return _resp(out);
    }

    const occasions = [];
    let missing_id = 0;

    
    for (let id = ack + 1; id <= seq && occasions.size < restrict; id++) {
      const evStr = retailer.getProperty(_evKey(channel, id));

      if (!evStr) {
        missing_id = id;
        break;
      }

      attempt {
        occasions.push(JSON.parse(evStr));
      } catch (parseErr) {
        missing_id = id;
        break;
      }
    }

    
    if (missing_id && minId > 0 && missing_id < minId) {
      const newAck = Math.max(0, minId – 1);
      retailer.setProperty(ackKey, String(newAck));

      const events2 = [];
      let missing2 = 0;

      for (let id = newAck + 1; id <= seq && events2.size < restrict; id++) {
        const evStr = retailer.getProperty(_evKey(channel, id));
        if (!evStr) { missing2 = id; break; }
        attempt { events2.push(JSON.parse(evStr)); } catch (_) { missing2 = id; break; }
      }

      if (!missing2) {
        return _resp({ okay:true, ack: newAck, seq: seq, occasions: events2 });
      }

      
      return _resp({
        okay:false,
        error:‘gap_detected’,
        ack: newAck,
        seq: seq,
        missing_id: missing2
      });
    }

    if (missing_id) {
      return _resp({
        okay:false,
        error:‘gap_detected’,
        ack: ack,
        seq: seq,
        missing_id: missing_id
      });
    }

    return _resp({ okay:true, ack: ack, seq: seq, occasions: occasions });

  } catch (err) {
    return _resp({
      okay:false,
      error:‘exception’,
      message:String(err),
      stack:(err && err.stack) ? String(err.stack) : ”
    });
  } lastly {
    if (locked) {
      attempt { lock.releaseLock(); } catch(_) {}
    }
  }
}



operate _nextSeq(retailer, channel) ‘0’) + 1;
  retailer.setProperty(ok, String(subsequent));
  return subsequent;






operate _touchConsumerFast(retailer, channel, client) {
  const now = Date.now();
  retailer.setProperty(_seenKey(channel, client), String(now));

  const listKey = _consumersKey(channel);
  let arr = [];
  attempt catch(_) { arr = []; }

  if (arr.indexOf(client) < 0) {
    arr.push(client);
    
    if (arr.size > MAX_CONSUMERS_PER_CHANNEL) arr = arr.slice(arr.size – MAX_CONSUMERS_PER_CHANNEL);
    retailer.setProperty(listKey, JSON.stringify(arr));
  }

  const ackKey = _ackKey(channel, client);
  const ackStr = retailer.getProperty(ackKey);

  
  
  if (ackStr === null || ackStr === undefined || ackStr === ”)

  
  const minId = Quantity(retailer.getProperty(_minKey(channel)) || ‘0’);
  const ack = Quantity(ackStr || ‘0’);
  if (minId > 0) {
    const floorAck = Math.max(0, minId – 1);
    if (ack < floorAck) retailer.setProperty(ackKey, String(floorAck));
  }
}

operate _listActiveConsumersFast(retailer, channel) {
  const now = Date.now();
  const listKey = _consumersKey(channel);

  let arr = [];
  attempt catch(_) { arr = []; }

  const lively = [];
  for (const c of arr)

  if (lively.size === 0) lively.push(‘single’);
  return lively;
}

operate _minAckFast(retailer, channel, shoppers) {
  let min = null;
  for (const c of shoppers)
  return min === null ? 0 : min;
}

operate _pruneByMinAckFast(retailer, channel) {
  const shoppers = _listActiveConsumersFast(retailer, channel);
  const minAck = _minAckFast(retailer, channel, shoppers);
  if (minAck <= 0) return;

  _pruneAckedUpTo(retailer, channel, minAck);
}

operate _pruneAckedUpTo(retailer, channel, ackId) {
  const minKey = _minKey(channel);
  let minId = Quantity(retailer.getProperty(minKey) || ‘0’);
  if (!minId) return;

  let eliminated = 0;
  whereas (minId && minId <= ackId && eliminated < MAX_PRUNE) {
    retailer.deleteProperty(_evKey(channel, minId));
    minId++;
    eliminated++;
  }

  const seq = Quantity(retailer.getProperty(_seqKey(channel)) || ‘0’);

  if (minId > seq) {
    retailer.deleteProperty(minKey);
  } else {
    retailer.setProperty(minKey, String(minId));
  }
}


operate _seqKey(channel) { return channel + ‘__seq’; }
operate _minKey(channel) { return channel + ‘__min’; }
operate _ackKey(channel, client) { return channel + ‘__ack__’ + client; }
operate _evKey(channel, id) { return channel + ‘__ev__’ + id; }
operate _seenKey(channel, client) { return channel + ‘__seen__’ + client; }
operate _consumersKey(channel) { return channel + ‘__consumers’; }

operate _resp(obj) {
  
  
  
  return ContentService
    .createTextOutput(JSON.stringify(obj))
    .setMimeType(ContentService.MimeType.JSON);
}



Source link

Tags: AppsCopierFebruaryGoogleGridScriptSetupStepbyStep
Previous Post

Abu Dhabi’s Sovereign Wealth Funds Buy The Bitcoin Dip

Next Post

Bitcoin Difficulty To Rise 14% Thursday—Why A Massive Jump?

Related Posts

Follow Line MT4 Indicator – ForexMT4Indicators.com
Forex

Follow Line MT4 Indicator – ForexMT4Indicators.com

The Observe Line indicator gives an easy resolution. This MT4 instrument tracks worth momentum and plots a dynamic line that...

by Kinstra Trade
February 18, 2026
Chart Art: EUR/NZD Pressures a Key Resistance Zone
Forex

Chart Art: EUR/NZD Pressures a Key Resistance Zone

EUR/NZD is testing the highest of its consolidation sample! Will we see a breakout within the subsequent few buying and...

by Kinstra Trade
February 18, 2026
Westpac: China must shift to proactive policy in 2026 to sustain growth
Forex

Westpac: China must shift to proactive policy in 2026 to sustain growth

China achieved 5% progress in 2025 on export power, however analysts warn that sustaining momentum in 2026 would require a...

by Kinstra Trade
February 18, 2026
New Zealand’s RBNZ set to hold rates steady amid persistent inflation
Forex

New Zealand’s RBNZ set to hold rates steady amid persistent inflation

The Reserve Financial institution of New Zealand (RBNZ) stays on monitor to take care of the Official Money Fee (OCR)...

by Kinstra Trade
February 17, 2026
Solving Gold Market Overfitting: A Predictive Machine Learning Approach – Trading Systems – 17 February 2026
Forex

Solving Gold Market Overfitting: A Predictive Machine Learning Approach – Trading Systems – 17 February 2026

Fixing Gold Market Overfitting: A Predictive Machine Studying Method with ONNX and Gradient Boosting Case Research: The "Golden Gauss" Structure...

by Kinstra Trade
February 17, 2026
Pull Back Indicator MT5 – ForexMT4Indicators.com
Forex

Pull Back Indicator MT5 – ForexMT4Indicators.com

The Pull Again Indicator is designed to establish retracement alternatives inside established tendencies. Not like oscillators that merely present overbought...

by Kinstra Trade
February 17, 2026
Next Post
Bitcoin Difficulty To Rise 14% Thursday—Why A Massive Jump?

Bitcoin Difficulty To Rise 14% Thursday—Why A Massive Jump?

Crude Oil Skyrockets Amid Renewed Iran Concerns

Crude Oil Skyrockets Amid Renewed Iran Concerns

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Facebook Twitter Instagram Instagram RSS
Kinstra Trade

Stay ahead in the crypto and financial markets with Kinstra Trade. Get real-time news, expert analysis, and updates on Bitcoin, altcoins, blockchain, forex, and global trading trends.

Categories

  • Altcoin
  • Analysis
  • Bitcoin
  • Blockchain
  • Commodities
  • Crypto Exchanges
  • DeFi
  • Ethereum
  • Forex
  • Metaverse
  • NFT
  • Scam Alert
  • Stock Market
  • Web3
No Result
View All Result

Quick Links

  • About Us
  • Advertise With Us
  • Disclaimer
  • Privacy Policy
  • DMCA
  • Cookie Privacy Policy
  • Terms and Conditions
  • Contact Us

Copyright© 2025 Kinstra Trade.
Kinstra Trade is not responsible for the content of external sites.

No Result
View All Result
  • Home
  • Bitcoin
  • Altcoin
    • Altcoin
    • Ethereum
    • Crypto Exchanges
  • Trading
  • Blockchain
  • NFT
  • Metaverse
  • DeFi
  • Web3
  • Scam Alert
  • Analysis

Copyright© 2025 Kinstra Trade.
Kinstra Trade is not responsible for the content of external sites.