"function generateTrade(stockQuant, stockPrice, fees, action, assetClass, broker, user, date, tradeType) {
  return {
    shares: stockQuant,
    price: stockPrice,
    fees: fees, // Added Fees
    action: action,
    assetClass: assetClass,
    broker: broker,
    user: user,
    date: date,
    type: tradeType
  };
}

function generateFifo(type, date, security, actions, quantity, price, fees, assetClass, broker, user) { // Added fees parameter
  let positionsMap = new Map();

  for (var i = 0; i < security.length; i++) {
    // Skip empty rows
    if (!security[i] && !actions[i] && !quantity[i] && !price[i] && !fees[i]) { // Included fees in check
      continue;
    }
    var currentType = type[i] ? type[i].toString().trim().toLowerCase() : '';
    var currentDate = date[i] ? new Date(date[i]) : new Date();
    var ticker = security[i] ? security[i].toString().trim() : '';
    var action = actions[i] ? actions[i].toString().trim().toLowerCase() : '';

    var stockQuant = Number(quantity[i]) || 0;
    var stockPrice = Number(price[i]) || 0;
    var feeAmount = Number(fees[i]) || 0; // Extract Fees

    var currentAssetClass = assetClass && assetClass[i] ? assetClass[i] : 'Unknown';
    var currentBroker = broker && broker[i] ? broker[i] : 'Unknown';
    var currentUser = user && user[i] ? user[i] : 'Unknown';

    let tradeType = '';  // Will determine this based on action

    // Only process delivery trades
    if (currentType === 'delivery') {
      if (action === 'buy') {
        tradeType = 'Long';
        let key = `${ticker}|${currentBroker}|${currentUser}|${currentAssetClass}|${tradeType}`;
        let trade = generateTrade(stockQuant, stockPrice, feeAmount, action, currentAssetClass, currentBroker, currentUser, currentDate, tradeType);
        let activeTrades = positionsMap.get(key);
        if (!activeTrades) {
          positionsMap.set(key, [trade]);
        } else {
          activeTrades.push(trade);
        }
      } else if (action === 'sell') {
        tradeType = 'Long';  // Selling from Long positions
        let key = `${ticker}|${currentBroker}|${currentUser}|${currentAssetClass}|${tradeType}`;
        let activeTrades = positionsMap.get(key);
        if (activeTrades) {
          let sharesToProcess = stockQuant;
          activeTrades.sort((a, b) => new Date(a.date) - new Date(b.date)); // ensure FIFO
          let iTrade = 0;
          while (sharesToProcess > 0 && iTrade < activeTrades.length) {
            let trade = activeTrades[iTrade];
            if (trade.shares <= sharesToProcess) {
              sharesToProcess -= trade.shares;
              activeTrades.splice(iTrade, 1);
            } else {
              trade.shares -= sharesToProcess;
              sharesToProcess = 0;
            }
          }
          if (activeTrades.length == 0) {
            positionsMap.delete(key);
          }
        }
      } else if (action === 'sellshort') {
        tradeType = 'Short';
        let key = `${ticker}|${currentBroker}|${currentUser}|${currentAssetClass}|${tradeType}`;
        let trade = generateTrade(stockQuant, stockPrice, feeAmount, action, currentAssetClass, currentBroker, currentUser, currentDate, tradeType);
        let activeTrades = positionsMap.get(key);
        if (!activeTrades) {
          positionsMap.set(key, [trade]);
        } else {
          activeTrades.push(trade);
        }
      } else if (action === 'buytocover') {
        tradeType = 'Short';  // Covering Short positions
        let key = `${ticker}|${currentBroker}|${currentUser}|${currentAssetClass}|${tradeType}`;
        let activeTrades = positionsMap.get(key);
        if (activeTrades) {
          let sharesToProcess = stockQuant;
          activeTrades.sort((a, b) => new Date(a.date) - new Date(b.date)); // ensure FIFO
          let iTrade = 0;
          while (sharesToProcess > 0 && iTrade < activeTrades.length) {
            let trade = activeTrades[iTrade];
            if (trade.shares <= sharesToProcess) {
              sharesToProcess -= trade.shares;
              activeTrades.splice(iTrade, 1);
            } else {
              trade.shares -= sharesToProcess;
              sharesToProcess = 0;
            }
          }
          if (activeTrades.length == 0) {
            positionsMap.delete(key);
          }
        }
      }
    } else if (currentType === 'corp. action' && action === 'split') {
      // process split
      let splitRatioStr = quantity[i].toString();
      let ratioParts = splitRatioStr.split(':');
      let numerator = parseFloat(ratioParts[0]);
      let denominator = parseFloat(ratioParts[1]);
      let ratio = numerator / denominator;
      positionsMap.forEach((value, pKey) => {
        if (pKey.startsWith(`${ticker}|`)) {
          value.forEach(trade => {
            trade.shares *= ratio;
            trade.price /= ratio;
          });
        }
      });
    } else if (currentType === 'my action') {
      if (action === 'transferfrom') {
        // Assuming transfer applies to Long positions
        tradeType = 'Long';
        let transferKey = `${ticker}|${currentBroker}|${currentUser}|${currentAssetClass}|${tradeType}`;
        let newBroker = broker[i + 1] ? broker[i + 1] : 'Unknown';
        let newKey = `${ticker}|${newBroker}|${currentUser}|${currentAssetClass}|${tradeType}`;
        let activeTrades = positionsMap.get(transferKey);
        if (activeTrades) {
          let sharesToTransfer = stockQuant;
          let totalAvailableShares = activeTrades.reduce((sum, trade) => sum + trade.shares, 0);
          if (sharesToTransfer > totalAvailableShares) {
            continue; // Skip this transfer if not enough shares
          }
          let transferredTrades = [];
          activeTrades.sort((a, b) => new Date(a.date) - new Date(b.date)); // ensure FIFO
          while (sharesToTransfer > 0 && activeTrades.length > 0) {
            let trade = activeTrades[0];
            if (trade.shares <= sharesToTransfer) {
              sharesToTransfer -= trade.shares;
              transferredTrades.push({ ...trade }); // Copy trade to new broker
              activeTrades.splice(0, 1);
            } else {
              let transferredTrade = { ...trade, shares: sharesToTransfer };
              trade.shares -= sharesToTransfer;
              sharesToTransfer = 0;
              transferredTrades.push(transferredTrade);
            }
          }
          if (activeTrades.length == 0) {
            positionsMap.delete(transferKey);
          }
          // Add transferred trades to new broker
          let newActiveTrades = positionsMap.get(newKey);
          if (!newActiveTrades) {
            positionsMap.set(newKey, transferredTrades);
          } else {
            newActiveTrades.push(...transferredTrades);
          }
        }
      }
    }
  }
  return positionsMap;
}

function myPositions(type, date, security, actions, quantity, price, fees, assetClass, broker, user) { // Added fees parameter
  let positionsMap = generateFifo(type, date, security, actions, quantity, price, fees, assetClass, broker, user); // Pass fees
  let returnArry = [['SN.', 'Ticker', 'Type', '# Shares', 'Avg. Buy @', 'Asset Class', 'Broker', 'User']];
  let sn = 1;
  let sortedKeys = Array.from(positionsMap.keys()).sort();
  sortedKeys.forEach(key => {
    let value = positionsMap.get(key);
    let totalShares = 0;
    let totalCost = 0;
    let totalFees = 0; // Initialize total fees
    let avgPrice = 0;
    let [ticker, currentBroker, currentUser, currentAssetClass, longOrShort] = key.split('|');
    value.forEach(trade => {
      totalShares += trade.shares;
      totalCost += trade.shares * trade.price;
      totalFees += trade.fees; // Accumulate fees
    });
    avgPrice = totalShares > 0 ? (totalCost + totalFees) / totalShares : 0; // Include fees in avg price

    returnArry.push([
      sn++,
      ticker,
      longOrShort,
      Number(totalShares.toFixed(2)), // **Shares as Number**
      avgPrice.toFixed(2),             // Avg. Buy @ remains as String
      currentAssetClass,
      currentBroker,
      currentUser
    ]);
  });
  return returnArry;
}"

ye code sahi average calculate kr rahah h fees include krke

"function updateOpenPortfolio() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getSheetByName("Trade Log");
  if (!sheet) {
    Logger.log("Trade Log sheet not found. Please check the sheet name.");
    return;
  }

  var portfolioSheet = ss.getSheetByName("Portfolio");
  if (!portfolioSheet) {
    portfolioSheet = ss.insertSheet("Portfolio");
  }

  // Set headers if they are not already set
  var headerRange = portfolioSheet.getRange('A3:H3');
  var currentHeaders = headerRange.getValues()[0];
  var newHeaders = ["SN.", "Ticker", "Type", "# Shares", "Avg. Buy @", "Asset Class", "Broker", "User"];

  // Only set headers if they are different
  if (JSON.stringify(currentHeaders) !== JSON.stringify(newHeaders)) {
    headerRange.setValues([newHeaders]);
  }

  // Clear existing data in columns A to H starting from row 4
  var lastRow = portfolioSheet.getLastRow();
  if (lastRow > 3) {
    portfolioSheet.getRange(4, 1, lastRow - 3, 8).clearContent(); // Clear only columns A to H
  }

  // Batch read data from the Trade Log
  var dataRange = sheet.getRange(2, 1, sheet.getLastRow() - 1, sheet.getLastColumn());
  var data = dataRange.getValues();

  if (data.length === 0) {
    Logger.log("No data found in Trade Log sheet.");
    return;
  }

  // Process header row
  var headers = data[0].map(header => header.toString().trim().toLowerCase());
  var expectedHeaders = {
    "type": ["type"],
    "date": ["date"],
    "security": ["security"],
    "action": ["action"],
    "quantity": ["quantity"],
    "@price": ["@price", "price"],
    "fees": ["fees"], // Added Fees
    "asset class": ["asset class"],
    "broker": ["broker"],
    "user": ["user"]
  };

  var headerIndices = {};
  var missingHeaders = [];

  for (var key in expectedHeaders) {
    var found = false;
    for (var i = 0; i < expectedHeaders[key].length; i++) {
      var possibleHeader = expectedHeaders[key][i].toLowerCase();
      var idx = headers.indexOf(possibleHeader);
      if (idx !== -1) {
        headerIndices[key] = idx;
        found = true;
        break;
      }
    }
    if (!found) {
      missingHeaders.push(key);
    }
  }

  if (missingHeaders.length > 0) {
    Logger.log("Missing Headers:", missingHeaders.join(", "));
    throw new Error("One or more required columns are missing in Trade Log sheet.");
  }

  var positionsMap = new Map();
  var pendingTransfers = {};

  function addPosition(ticker, assetClass, broker, user, position) {
    var key = `${ticker}|${assetClass}|${broker}|${user}`; // Changed delimiter to '|'
    if (!positionsMap.has(key)) {
      positionsMap.set(key, []);
    }
    positionsMap.get(key).push(position);
  }

  function removePositions(ticker, assetClass, broker, user, quantity) {
    var key = `${ticker}|${assetClass}|${broker}|${user}`; // Changed delimiter to '|'
    var remainingQuantity = quantity;
    var removedPositions = [];

    if (positionsMap.has(key)) {
      var positions = positionsMap.get(key);
      positions.sort((a, b) => new Date(a.date) - new Date(b.date)); // FIFO
      positionsMap.set(key, positions.filter(pos => {
        if (remainingQuantity <= 0) return true;
        if (pos.quantity <= remainingQuantity) {
          removedPositions.push({ ...pos });
          remainingQuantity -= pos.quantity;
          return false;
        } else {
          var splitPos = { ...pos, quantity: remainingQuantity };
          removedPositions.push(splitPos);
          pos.quantity -= remainingQuantity;
          remainingQuantity = 0;
          return true;
        }
      }));
    }
    return removedPositions;
  }

  for (var i = 1; i < data.length; i++) {
    var row = data[i];

    // Check if the row is empty
    if (row.every(cell => cell === "")) {
      continue; // Skip empty rows
    }

    var type = row[headerIndices["type"]].toString().trim().toLowerCase();
    var date = new Date(row[headerIndices["date"]]);
    var action = row[headerIndices["action"]].toString().trim().toLowerCase();
    var ticker = row[headerIndices["security"]].toString().trim();
    var quantity = parseFloat(row[headerIndices["quantity"]]) || 0;
    var price = parseFloat(row[headerIndices["@price"]]) || 0.0;
    var fees = parseFloat(row[headerIndices["fees"]]) || 0.0; // Extract Fees
    var assetClass = row[headerIndices["asset class"]].toString().trim();
    var broker = row[headerIndices["broker"]].toString().trim();
    var user = row[headerIndices["user"]].toString().trim();

    var formattedDate = Utilities.formatDate(date, "Asia/Kolkata", "dd-MMM-yyyy");

    if (type === "delivery") {
      if (action === "buy" || action === "sellshort") {
        addPosition(ticker, assetClass, broker, user, {
          date: formattedDate,
          quantity: quantity,
          price: price,
          fees: fees, // Include Fees
          tradeType: action === "buy" ? "Long" : "Short"
        });
      } else if (action === "sell" || action === "buytocover") {
        removePositions(ticker, assetClass, broker, user, quantity);
      }
    } else if (type === "my action") {
      if (action === "transferfrom") {
        var transferKey = `${ticker}|${assetClass}|${quantity}|${formattedDate}|${broker}|${user}`; // Changed delimiter to '|'
        pendingTransfers[transferKey] = removePositions(ticker, assetClass, broker, user, quantity);
      } else if (action === "transferto") {
        var transferKey = `${ticker}|${assetClass}|${quantity}|${formattedDate}`; // Changed delimiter to '|'
        var matchingTransfer = Object.keys(pendingTransfers).find(key => key.startsWith(transferKey));
        if (matchingTransfer) {
          pendingTransfers[matchingTransfer].forEach(pos =>
            addPosition(ticker, assetClass, broker, user, pos)
          );
          delete pendingTransfers[matchingTransfer];
        } else {
          Logger.log(`Warning: No matching transfer found for TransferTo action: ${ticker}, ${quantity}, ${formattedDate}`);
        }
      }
    } else if (type === "corp. action" && action === "split") {
      var splitRatio = eval(quantity.toString().replace(":", "/")); // Convert "2:1" to 2/1
      for (var key of positionsMap.keys()) {
        // Check if the key starts with the ticker (ignoring asset class)
        if (key.startsWith(`${ticker}|`)) { // Changed delimiter to '|'
          positionsMap.get(key).forEach(function(pos) {
            if (pos.tradeType === "Long") {
              pos.quantity *= splitRatio; // Adjust quantity for long positions
              pos.price /= splitRatio; // Adjust price for long positions
            } else if (pos.tradeType === "Short") {
              pos.quantity *= splitRatio; // Adjust quantity for short positions
              pos.price /= splitRatio; // Adjust price for short positions
            }
          });
        }
      }
    }
  }

  // Prepare data for output
  var consolidatedPositions = {};

  for (var key of positionsMap.keys()) {
    var [ticker, assetClass, broker, user] = key.split('|'); // Changed delimiter to '|'
    var totalQuantity = 0;
    var totalValue = 0;
    var totalFees = 0; // Initialize total fees

    positionsMap.get(key).forEach(function(pos) {
      if (pos.quantity > 0) {
        totalQuantity += pos.quantity;
        totalValue += pos.quantity * pos.price;
        totalFees += pos.fees; // Accumulate fees
      }
    });

    if (totalQuantity > 0) {
      var avgPrice = (totalValue + totalFees) / totalQuantity; // Include fees in avg price
      var consolidationKey = `${ticker}|${assetClass}|${broker}|${user}`; // Changed delimiter to '|'
      consolidatedPositions[consolidationKey] = {
        ticker: ticker,
        type: positionsMap.get(key)[0].tradeType,
        quantity: totalQuantity,
        avgPrice: avgPrice,
        assetClass: assetClass,
        broker: broker,
        user: user
      };
    }
  }

  // Convert consolidated positions to array and sort by ticker
  var output = Object.values(consolidatedPositions);
  output.sort((a, b) => a.ticker.localeCompare(b.ticker));

  // Add Sl No. and prepare final sorted output
  var sortedOutput = output.map((item, index) => [
    index + 1, // SN.
    item.ticker,
    item.type,
    Number(item.quantity.toFixed(2)), // Format quantity as Number
    item.avgPrice.toFixed(2),           // Format average price
    item.assetClass,
    item.broker,
    item.user
  ]);

  // Output to "Portfolio" sheet without affecting formatting
  if (sortedOutput.length > 0) {
    portfolioSheet.getRange(4, 1, sortedOutput.length, sortedOutput[0].length).setValues(sortedOutput);
    portfolioSheet.getRange(4, 4, sortedOutput.length, 2).setNumberFormat('#,##0.00');
  } else {
    Logger.log("No open positions to display.");
  }

  // Record the last update date and time
  let now = new Date();
  let formattedNow = Utilities.formatDate(now, "Asia/Kolkata", "dd-MMM-yyyy HH:mm:ss");
  portfolioSheet.getRange('V1').setValue(formattedNow);

  Logger.log("Open portfolio updated successfully.");
}"

ye average galat calculate kr raha h fees include krke.

dono ko fees include krke average calculate krna h.

pr first code sahi kr rahah h second code nhi.

dekho process same h kya .

pehle batao kuch difference h ya nhi firr aage baat krte h